2011-08-14 31 views
9

編譯我有以下結構:協變返回類型的接口不通過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 
+0

與open-jdk編譯器版本1.6.0_22相同的問題。但它在java7中工作。 –

+0

只是測試它,是的,所以它 - 很好。 –

+0

可能[重複](http://stackoverflow.com/questions/11343238/java-implementing-multiple-interfaces-with-same-method-and-different-return-ty)? – amaidment

回答

3

您在FooBar界面中同時擴展Foo和Bar。因此,您繼承了兩個不兼容的返回類型的方法。 Java協方差只有在Liskov替換之後才被允許。也就是說,覆蓋的候選類型幾乎都是重寫的返回類型的一個子類。

在你上面的例子是這樣的應該編譯:

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

public interface Foo { 
    FooReturn fooBar(); 
} 

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

在OP的代碼中,重寫方法的返回類型* do *子類型重寫方法的返回類型。所以從學術的角度來看,OP的代碼不應該是有效的。 –

1

在這個javaranch discussion的答案似乎表明這是一個javac錯誤。但是,參考的bug url似乎不起作用。

+0

看起來像[JDK-7u4](http://www.oracle。com/technetwork/java/javase/downloads/jdk-7u4-downloads-1591156.html)修復了這個錯誤。 – Georg

1

作爲一種變通方法,你可以做

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

不漂亮,但應該做的伎倆。

+1

謝謝,這是一個好主意 - 然而,因爲它與OpenJDK 7的javac編譯和eclipse編譯器編譯,我可以在不引入額外類型的情況下解決它。 –

+1

這似乎不起作用,jdk6的javac仍然說'類型Bar1和Foo1不兼容;都定義fooBar(),但是具有不相關的返回類型。 –

1

我有同樣的問題,它似乎很好,使用Oracle的JDK 7。