此代码:
interface I {}
public class Test {
TableView<? extends I> table;
Test(ObservableList<? extends I> list) {
table = new TableView<>();
table.setItems(list);
}
}
...生成此消息:
error: method setItems in class TableView<S> cannot be applied to given types;
table.setItems(list);
required: ObservableList<CAP#1>
found: ObservableList<CAP#2>
reason: argument mismatch; ObservableList<CAP#2> cannot be converted to ObservableList<CAP#1>
where S is a type-variable:
S extends Object declared in class TableView
where CAP#1,CAP#2 are fresh type-variables:
CAP#1 extends I from capture of ? extends I
CAP#2 extends I from capture of ? extends I
两种相同类型之间的类型不匹配怎么样?我错过了什么?
答案 0 :(得分:5)
在Java Generics中,?
通配符不能相同,因为它们代表未知类型。未知类型不能等于其他未知类型。
如果您希望匹配类型,则必须在Test
类上定义泛型类型参数,并在整个班级中引用它。
public class Test<T extends I> {
TableView<T> table;
Test(ObservableList<T> list) {
table = new TableView<>();
table.setItems(list);
}
}
答案 1 :(得分:2)
Collection<?> c = new ArrayList<String>();
c.add(new Object()); // Compile time error
“由于我们不知道c的元素类型代表什么,我们不能向它添加对象.add()方法接受类型E的参数,即集合的元素类型。当实际的类型参数是?,它代表一些未知类型。我们传递给add的任何参数都必须是这个未知类型的子类型。由于我们不知道它是什么类型,我们不能传入任何内容。唯一的例外是null,是各种类型的成员。
另一方面,给定List,我们可以调用get()并使用结果。结果类型是未知类型,但我们始终知道它是一个对象。因此,可以安全地将get()的结果赋给Object类型的变量,或者将其作为期望Object类型的参数传递。“(http://docs.oracle.com/javase/tutorial/extra/generics/wildcards.html)
答案 2 :(得分:1)
请勿在变量声明中使用“?extends I”。它不会增加语义值,是您问题的根源。你看到编译器拒绝假设'?'在一个声明中与'?'相同在另一个。这很自然,因为不能保证它们是自然的。我会免除'?'共:
interface I {}
public class Test {
TableView<I> table;
Test(ObservableList<? extends I> list) {
table = new TableView<>();
table.setItems(list);
}
}