接口中的协变返回类型未通过 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
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/java/FooReturn.java /tmp/covariant/src/main/java/FooBar.java -g -nowarn -target 1.6 -source 1.6
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
JLS (§9.4.1) 说:
所以我想说 javac 是正确的。但这对我来说看起来像是律师行话,所以我可能是错的。
The JLS (§9.4.1) says :
So I would say that javac is right. But this looks like lawyer jargon to me, so I could be wrong.
这个 javaranch 讨论 中的答案似乎是表明这是一个 javac bug。但是,引用的 bug url 似乎不起作用。
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.
我也遇到了同样的问题,使用 Oracle 的 JDK 7 似乎没问题。
I had the same problem and it seems to be fine by using the JDK 7 from Oracle.
作为一种解决方法,你可以做得
不漂亮,但应该能达到目的。
As a workaround, you could do
Not pretty but should do the trick.
这是 Sun Java 6 编译器中的错误。
This is a bug in Sun's Java 6 compiler.
您正在 FooBar 界面中扩展 Foo 和 Bar。因此,您继承了两个返回类型不兼容的方法。 Java 协方差仅在遵循 Liskov 替换时才被允许。也就是说,重写的候选类型几乎必须是重写的返回类型的子类。
在上面的示例中,类似这样的内容应该编译:
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: