本文介绍了协变器返回类型在界面不通过Javac进行编译的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下结构:

  public interface BarReturn {} 
public interface FooReturn {}
public interface FooBarReturn扩展FooReturn,BarReturn {}

public interface Foo {
FooReturn fooBar();
}

public interface Bar {
BarReturn fooBar();
}

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

Javac失败,并显示以下消息:

  FooBar.java:2:类型Bar和Foo不兼容;都定义fooBar(),但是使用不相关的返回类型
public interface FooBar extends Foo,Bar {
^
1 error


这是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接口。因此,您继承了具有不兼容返回类型的两种方法。只有当跟随Liskov替换时,才允许Java协方差。 Aka,首选的候选类型必须几乎是覆盖的返回类型的子类。



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

公共接口BarReturn {} 
public interface FooReturn {}
public interface FooBarReturn扩展FooReturn,BarReturn {}

public interface Foo {
FooReturn fooBar();
}

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


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
解决方案

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();
}

这篇关于协变器返回类型在界面不通过Javac进行编译的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-10 05:46