我尝试将类型为SubTest
的对象添加到具有通用类型T
的列表中,该列表定义为<T extends SubTest>
。我希望这可行,但编译器告诉我它无法将SubTest
转换为T
。我在这里看不到问题。
以下是完整代码:
public class Test<T extends Test.SubTest> {
private List<T> list = new ArrayList<T>();
public void add() {
list.add(new SubTest()); //<- compile error here
}
protected static class SubTest {
}
}
是的,我知道我可以简单地写
list.add((T) new SubTest());
它会起作用。但问题是:为什么它不起作用 没有不必要的演员?
答案 0 :(得分:3)
类型参数T
可以是SubTest
,但它也可以是SubTest
的任何潜在子类。如果T
是这样的子类,那么您就不能add
SubTest
到list
,因为它是超类。
因为编译器不知道哪个类T
确实存在,所以它不允许您将SubTest
传递给add
;它可能违反了类型安全性,Java泛型可以帮助您维护。
转换为T
将允许您编译它,因为可能有效的演员告诉编译器,&#34;我知道我在做什么,这将起作用&#34;。然而,这可能导致如上所述的类型安全违规。这可能在运行时在ClassCastException
中表现出来,类似于&#34;无法将SubSubTest转换为SubTest&#34; (如果T
为SubSubTest
,则为SubTest
)的子类。
答案 1 :(得分:0)
因为SubTest
是T
的超类。当您将变量l
声明为List<T>
类型时,您明确表示l
的内容至少是T
类型的内容,以及任何客户端代码应该能够执行T
对列表中任何项目公开的所有操作。由于T
可能比SubTest
更具体,因此您无法将SubTest
实例添加到l
,因为此实例不一定会遵守T
的合同