Java 爪哇语:“什么?”;?扩展I“;无法转换为“?”;?扩展I“;

Java 爪哇语:“什么?”;?扩展I“;无法转换为“?”;?扩展I“;,java,generics,Java,Generics,此代码: interface I {} public class Test { TableView<? extends I> table; Test(ObservableList<? extends I> list) { table = new TableView<>(); table.setItems(list); } } 接口I{} 公开课考试{ TableView在Java泛型中,?通配符不

此代码:

interface I {}

public class Test {

    TableView<? extends I> table;

    Test(ObservableList<? extends I> list) {
        table = new TableView<>();
        table.setItems(list);
    }
}
接口I{}
公开课考试{

TableView在Java泛型中,
通配符不能相同,因为它们表示未知类型。未知类型不能等于其他未知类型

如果希望类型匹配,则必须在
Test
类上定义泛型类型参数,并在整个类中引用它

public class Test<T extends I> {

    TableView<T> table;

    Test(ObservableList<T> list) {
        table = new TableView<>();
        table.setItems(list);
    }
}
公共类测试{
表视图表;
测试(可观察列表){
table=新的TableView();
表2.设置项目(列表);
}
}
集合c=new ArrayList();
c、 添加(新对象());//编译时错误
“因为我们不知道c的元素类型代表什么,所以我们不能向它添加对象方法接受类型为E的参数,即集合的元素类型。当实际类型参数为?时,它表示某个未知类型。我们传递要添加的任何参数都必须是此未知类型的子类型。因为我们不知道这是什么类型,所以无法传递任何内容。唯一的例外是null,它是每个类型的成员。

另一方面,给定一个列表,我们可以调用get()并使用结果。结果类型是未知类型,但我们始终知道它是一个对象。因此,可以安全地将get()的结果分配给object类型的变量,或将其作为预期类型对象的参数传递。“()

不要使用”?“扩展I”在变量声明中。它不添加任何语义值,并且是问题的根源。您可以看到编译器拒绝假定一个声明中的“?”与另一个声明中的“?”相同。这是很自然的,因为无法保证它们是相同的。我完全不使用“?”:

interface I {}

public class Test {

    TableView<I> table;

    Test(ObservableList<? extends I> list) {
        table = new TableView<>();
        table.setItems(list);
    }
}
接口I{}
公开课考试{
表视图表;

试验(可观察的)昨天我吃了一些水果。例如,
?extends fruit
今天我吃了一些水果。
?extends fruit
。有人能从这些信息中假设,我两天都吃了相同类型的水果吗?没有。
一些水果#1
可能不是
一些水果#2
甚至更好:除非你真的在写一些,否则不要使用泛型要分发并允许扩展的通用组件(根据打开/关闭原则)。
Collection<?> c = new ArrayList<String>();
c.add(new Object()); // Compile time error
interface I {}

public class Test {

    TableView<I> table;

    Test(ObservableList<? extends I> list) {
        table = new TableView<>();
        table.setItems(list);
    }
}