接口中的协变返回类型不通过Javac进行编译

我有以下结构:

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失败并显示以下消息:

 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 

但是,Eclipse可以编译得很好,据我所知它应该编译–FooBar的fooBar()方法通过使用协变返回来满足Foo和Bar的fooBar()方法的约定。

这是Eclipse编译或javac中的错误吗? 或者有没有办法说服javac编译它? 作为参考,我的javac选项如下所示:

 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/java/FooReturn.java /tmp/covariant/src/main/java/FooBar.java -g -nowarn -target 1.6 -source 1.6 

您正在FooBar界面中扩展Foo和Bar。 因此,您inheritance了两种具有不兼容返回类型的方法。 只有当它跟随Liskov替换时才允许Java协方差。 Aka,重写的候选类型必须几乎是重写的返回类型的子类。

在上面的例子中,这样的东西应该编译:

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

JLS(§9.4.1)说:

接口可以使用覆盖等效签名(第8.4.2节)inheritance多个方法。 这种情况本身并不会导致编译时错误。 该接口被认为是inheritance所有方法。 但是,其中一个inheritance的方法必须是可替换任何其他inheritance方法的返回类型; 否则,发生编译时错误(在这种情况下throws子句不会导致错误。)

所以我会说javac是对的。 但这对我来说就像是律师行话,所以我可能错了。

这个javaranch讨论中的答案似乎表明它是一个javac错误。 但是,引用的bug url似乎不起作用。

我遇到了同样的问题,使用Oracle的JDK 7似乎没问题。

作为一种解决方法,你可以做到

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

不漂亮,但应该做的伎俩。

这是Sun的Java 6编译器中的一个错误 。