类型推断涉及返回类型,通配符和交集类型
我正在尝试声明一个包含一个方法的接口,该方法将返回实现Comparator
和Action
的事物列表,即
<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();
实现此效果的另一种方法是创建一个空接口,该接口扩展Comparator
和Action
并将其用作返回类型,即
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
List extends Action> things = getThings(); List extends Comparator
编辑这是我的第一反应。 然后我想到了它,我不认为推断可以工作,所以我删除了答案。
再次检查规格,他们应该工作。 它在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 extends Action> >> List Comparable >> T Action >> T
产量
T :< Action T :< Comparable
因此T=Comparable & Action
当您返回类似的List
, T
指的是某些(未知)类型,它是Action
和Comparator
的子类型,并且是列表中所有元素的(最好是最低的)公共超类型。 如果这种类型不存在,您可能会遇到问题。
如果您不关心T
是什么,您可以使用类型变量,如Dave Costa建议的那样,或者您可以使用通配符
List extends Action> l = getThings(); List extends Comparator