开发者

Covariant Return Type in Interface not compiling via Javac

I have the following structure:

public interface BarReturn {}
public interface FooReturn {}
public interface FooBarReturn extends FooReturn, BarReturn {}

public interface Foo {  
  FooReturn fooBar( );
}

public interface Bar {
  BarReturn fooBar();
}

public interface FooBar extends Foo, Bar {
  FooBarReturn fooBar();
}

Javac fails with the following message:

FooBar.java:2: types Bar and Foo are incompatible; both define fooBar(), but with unrelated return types
public interface FooBar extends Foo, Bar {
       ^
1 error

However, Eclipse can compile it fine, and as far as I can see it should compile - FooBar's fooBar() method satisfies the contract of both Foo and Bar's fooBar() method by using covariant returns.

Is this a bug in the Eclipse compile or in javac? Or is there a way to persuade javac to compile it? For reference my javac options look like this:

javac -d /tmp/covariant/target/classes -sourcepath /tmp/covariant/src/main/java: /tmp/covariant/src/main/java/Foo.java /tmp/covariant/src/main/java/BarReturn.java /tmp/covariant/src/main/java/FooBarReturn.java /tmp/covariant/src/main/java/Bar.java /tmp/covariant/src/main/开发者_如何学JAVAjava/FooReturn.java /tmp/covariant/src/main/java/FooBar.java -g -nowarn -target 1.6 -source 1.6


You are extending both Foo and Bar in your FooBar interface. As such you are inheriting two methods with incompatible return types. Java co-variance is only allowed when it follows Liskov substitution. Aka, the overriding candidate types must pretty much be a subclass of the overridden return type.

In your example above something like this should compile:

public interface BarReturn {}
public interface FooReturn {}
public interface FooBarReturn extends FooReturn, BarReturn {}

public interface Foo {  
  FooReturn fooBar( );
}

public interface FooBar extends Foo{
  FooBarReturn fooBar();
}


The JLS (§9.4.1) says :

It is possible for an interface to inherit several methods with override-equivalent signatures (§8.4.2). Such a situation does not in itself cause a compile-time error. The interface is considered to inherit all the methods. However, one of the inherited methods must must be return type substitutable for any other inherited method; otherwise, a compile-time error occurs (The throws clauses do not cause errors in this case.)

So I would say that javac is right. But this looks like lawyer jargon to me, so I could be wrong.


An answer in this javaranch discussion seems to suggest that it's a javac bug. However, the referenced bug url doesn't seem to work.


I had the same problem and it seems to be fine by using the JDK 7 from Oracle.


As a workaround, you could do

interface Foo1 extends Foo {
  FooBarReturn fooBar();
}
interface Bar1 extends Bar {
  FooBarReturn fooBar();
}
public interface FooBar extends Foo1, Bar1 { }

Not pretty but should do the trick.


This is a bug in Sun's Java 6 compiler.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜