是否可能出现以下内容:
Widget w = Gadet<Widget>().getInstance();
(编辑:getInstance调用返回新创建的指定泛型类型参数的实例) 我知道java的类型擦除(至少在某种程度上)。但是当我遇到
时,我有点困惑this.instanceClass = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
on hibernate.org
答案 0 :(得分:2)
你想传入任何类,并获得该类型的实例 - 静态,即没有反射?不,这是不可能的 - 由于类型擦除,对。
传递任何类的唯一方法是将其作为参数传递:
Object getInstance(Class clz){ ... };
即使您将其定义为
Object getInstance(Class<T> clz){ ... };
T在运行时丢失。你所拥有的就是上课。我认为语言设计师可以通过允许以下内容使其更甜美。
new T()
引擎盖下会做clz.newInstance(),但他们没有。
答案 1 :(得分:2)
嗯...要完全回答你的问题,需要一些背景知识:
擦除意味着实际类型参数不包含在字节码中,因此类型参数的动态类型在运行时是未知的,因此通常无法实现它。 (这就是为什么类型参数T的new T()
不能编译的原因。)
但是,在字段,方法或类的声明中指定的实际类型参数将记录在类文件中,并可用于反射。在某些情况下,后一信息足以确定类型参数的值。
例如,hibernate网站的片段(如果在类C<T>
中声明),如果T
是getClass()
的直接和非通用子类,则推断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;
}
}