Java Generics:编译器虽然兼容,但不会推断类型

时间:2015-08-25 22:18:43

标签: java generics casting

我尝试将类型为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());

它会起作用。但问题是:为什么它不起作用 没有不必要的演员?

2 个答案:

答案 0 :(得分:3)

类型参数T可以是SubTest,但它也可以是SubTest的任何潜在子类。如果T是这样的子类,那么您就不能add SubTestlist,因为它是超类。

因为编译器不知道哪个类T确实存在,所以它不允许您将SubTest传递给add;它可能违反了类型安全性,Java泛型可以帮助您维护。

转换为T将允许您编译它,因为可能有效的演员告诉编译器,&#34;我知道我在做什么,这将起作用&#34;。然而,这可能导致如上所述的类型安全违规。这可能在运行时在ClassCastException中表现出来,类似于&#34;无法将SubSubTest转换为SubTest&#34; (如果TSubSubTest,则为SubTest)的子类。

答案 1 :(得分:0)

因为SubTestT超类。当您将变量l声明为List<T>类型时,您明确表示l的内容至少是T类型的内容,以及任何客户端代码应该能够执行T对列表中任何项目公开的所有操作。由于T可能比SubTest更具体,因此您无法将SubTest实例添加到l,因为此实例不一定会遵守T的合同