Java泛型(类型擦除)

时间:2009-10-02 18:41:22

标签: java generics

是否可能出现以下内容:

Widget w = Gadet<Widget>().getInstance();

(编辑:getInstance调用返回新创建的指定泛型类型参数的实例) 我知道java的类型擦除(至少在某种程度上)。但是当我遇到

时,我有点困惑
this.instanceClass = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];

on hibernate.org

3 个答案:

答案 0 :(得分:2)

你想传入任何类,并获得该类型的实例 - 静态,即没有反射?不,这是不可能的 - 由于类型擦除,对。

传递任何类的唯一方法是将其作为参数传递:

Object getInstance(Class clz){ ... };

即使您将其定义为

Object getInstance(Class<T> clz){ ... };

T在运行时丢失。你所拥有的就是上课。我认为语言设计师可以通过允许以下内容使其更甜美。

new T()

引擎盖下会做clz.newInstance(),但他们没有。

答案 1 :(得分:2)

嗯...要完全回答你的问题,需要一些背景知识:

擦除意味着实际类型参数不包含在字节码中,因此类型参数的动态类型在运行时是未知的,因此通常无法实现它。 (这就是为什么类型参数T的new T()不能编译的原因。)

但是,在字段,方法或类的声明中指定的实际类型参数将记录在类文件中,并可用于反射。在某些情况下,后一信息足以确定类型参数的值。

例如,hibernate网站的片段(如果在类C<T>中声明),如果TgetClass()的直接和非通用子类,则推断C的实际类型。 1}},通过反思该类声明的extends子句。 (如果该extends子句包含另一个类型变量,如class D<T> extends C<T>中所述,则该方法在尝试将类型变量强制转换为Class<?>时会抛出ClassCastException。

如果可以将该代码段推广到任何非泛型getClass()(直接或其他),但如果getClass()是通用的,则运行时保留的有关类型参数的有限信息不足以确定类型。< / p>

答案 2 :(得分:1)

您可以执行以下操作:

public static <T> T getInstance(Class<T> klass) {
    try {
        return klass.newInstance();
    } catch (Exception ex) {
         //Do some real error handling here probably
         return null;
     }
 }
相关问题