类型推断涉及返回类型,通配符和交集类型

我正在尝试声明一个包含一个方法的接口,该方法将返回实现ComparatorAction的事物列表,即

 <T extends Comparator & Action> List getThings(); 

这编译很好,但问题出现在我尝试调用此方法时。 我希望能够做到这一点:

 List things = getThings(); List<Comparator> things = getThings(); 

当我尝试这样做时,我得到以下编译错误:

  incompatible types; no instance(s) of type variable(s) T exist so that java.util.List conforms to java.util.List found : java.util.List required: java.util.List 

以下内容也不起作用:

 List things = getThings(); List<? extends Comparator> things = getThings(); 

实现此效果的另一种方法是创建一个空接口,该接口扩展ComparatorAction并将其用作返回类型,即

 public interface ComparatorAction extends Comparator, Action { } List getThings(); 

但我不想这样做。 必须有办法做我想做的事,对吧? 有任何想法吗?

谢谢!

PS我很难为这篇文章提供一个好头衔,所以随时可以改变它。

您还可以参数化调用getThings() 。 例如:

 public static  & Action> void main(String[] args) { List l = getThings(); Action a = l.get(0); Comparator c = l.get(0); } 
 List things = getThings(); List> things = getThings(); 

编辑这是我的第一反应。 然后我想到了它,我不认为推断可以工作,所以我删除了答案。

再次检查规格,他们应该工作。 它在JDK7中编译,但在JDK6中失败。 我猜他们已修复了一个错误。

编辑2不…我再次阅读规范(JLS3#15.12.2.8),现在我不认为推理应该有效。 JDK6拒绝推断是正确的。 (我怀疑JDK7引入了一个新的错误;推理规则可能会更新,因此JDK7根据新规则是正确的。我不确定)

根据JLS3,首先有一个通配符捕获,引入了一个新的类型参数W ,它具有上限Action 。 然后推理有这些初始约束:

 List >> List Comparable >> T Action >> T 

第一个约束产生等式约束T=W ,就是这样,推断就完成了。

现在编译器将检查推断的T满足其边界,即是否

 W :< Comparable W :< Action 

答案是否定的,第一界不能满足。 (IntelliJ显示了一个很好的错误消息(优于javac):“推断类型'?extends Action' (即W) ,类型参数'T'不在其范围内;应该实现Comparable”)

编辑3问题是在推理之前是否应该存在通配符捕获。 这对我来说不太清楚。 如果不存在,那么我们就有了

 List >> List Comparable >> T Action >> T 

产量

 T :< Action T :< Comparable 

因此T=Comparable & Action

当您返回类似的ListT指的是某些(未知)类型,它是ActionComparator的子类型,并且是列表中所有元素的(最好是最低的)公共超类型。 如果这种类型不存在,您可能会遇到问题。

如果您不关心T是什么,您可以使用类型变量,如Dave Costa建议的那样,或者您可以使用通配符

 List l = getThings(); List> l2 = getThings();