Java 为什么键入列表的元素<&燃气轮机;在子类中使用时强制转换为对象

Java 为什么键入列表的元素<&燃气轮机;在子类中使用时强制转换为对象,java,generics,types,casting,Java,Generics,Types,Casting,有人能解释一下为什么在子类中使用类型化的列表的元素时将强制转换为对象 只有父类使用泛型时才会发生这种情况。 在某些情况下,类的type如何干扰实例字段的type public abstract class Parent<T> { protected List<String> myList = Arrays.asList("Hello", "World"); void method1(){ myList.get(0).substring(0

有人能解释一下为什么在子类中使用类型化的
列表
的元素时将强制转换为
对象
只有父类使用泛型时才会发生这种情况。

在某些情况下,类的
type
如何干扰实例字段的
type

public abstract class Parent<T> {
    protected List<String> myList = Arrays.asList("Hello", "World");

    void method1(){
        myList.get(0).substring(0, 1); //ok
    }
}


public class Child<T> extends Parent {
    void method2(){
        myList.get(0).substring(0, 1); //compilation error. myList.get(0) is of type Object and not of type String
        ((String) myList.get(0)).substring(0, 1); // works good, but why we need to cast 
    }
}
这就是问题所在:

public class Child extends Parent
由于您使用了
父项
,因此
父项
定义中的所有泛型都将丢失。发件人:

原始类型的超类(分别是超级接口)是泛型类型的任何参数化的超类(超级接口)的擦除

“擦除”部分是“你失去了所有的泛型”的行话

Child
中引用类型参数时,需要指定类型参数。例如,您可以保留一个非泛型子类:

公共类子级扩展父级
或者将子类也设置为泛型:

public class Child<T> extends Parent<T>
公共类子级扩展父级

很有趣。即使您正在扩展原始类型
父类
,编译器也会看到与
列表
的无关类型参数的类型参数的连接,这一点得到了广泛的回答,包括相关的JLS引号。@ernest_k:see-当原始类型用作超类时,使用了对整个类型的擦除,所以所有泛型都丢失了。@JonSkeet谢谢,这很有帮助。我不明白为什么会是这样。@ernest_k:我怀疑它简化了事情——记住原始类型的意义在于与根本不理解泛型的代码兼容。是的,我需要父类是泛型的,但我需要在父类中存在一个类型列表,并避免在所有子类中强制转换。@Ermal:您真的想调用类型参数
Integer
?这是一个非常容易混淆的类型参数名称。但基本上,如果您真的需要父类是泛型的(请注意,类型参数没有在您显示的任何地方使用),那么您的子类应该使用泛型超类。我将在答案中添加一个例子。Jon Skeet,关于类型参数的
Integer
,您是对的。我的错误是,在我的应用程序中我有
,我用
整数进行了简化,导致了一个不好的例子。将
子项
设置为泛型也不能解决问题。不管怎么说,答案被接受了,你们的答案很清楚为什么会发生这种情况。(对不使用泛型的推动较少:p)谢谢。(我将更新问题,清除所有边缘疑问)@Ermal:“使子项也通用,并不能解决问题。”-确实如此,只要您确保为
Parent
指定类型参数@Ermal:我已经修正了我的答案,以解释您的问题编辑,但在将来,如果编辑会让答案变得毫无意义的话,最好不要问问题,或者只是添加一些东西,就像在本例中那样。
public class Child<T> extends Parent<T>