this question的已接听答案介绍了如何在T
课程中创建Generic<T>
的实例。这涉及将Class<T>
参数传递给Generic
构造函数并从中调用newInstance
方法。
然后创建Generic<Bar>
的新实例,并传入参数Bar.class
。
如果新Generic
类的泛型类型参数不是像Bar
这样的已知类,但它本身是泛型类型参数,您会怎么做?假设我有一些其他类Skeet<J>
,我想从该类中创建一个Generic<J>
的新实例。然后,如果我尝试传入J.class
,我会收到以下编译器错误:
cannot select from a type variable.
有什么方法吗?
触发错误的代码的具体位是:
public class InputField<W extends Component & WidgetInterface>
extends InputFieldArray<W>
{
public InputField(String labelText)
{
super(new String[] {labelText}, W.class);
}
/* ... */
}
public class InputFieldArray<W extends Component & WidgetInterface>
extends JPanel
{
/* ... */
public InputFieldArray(String[] labelText, Class<W> clazz)
throws InstantiationException, IllegalAccessException
{
/* ... */
for (int i = 0 ; i < labelText.length ; i++) {
newLabel = new JLabel(labelText[i]);
newWidget = clazz.newInstance();
/* ... */
}
/* ... */
}
/* ... */
}
发生错误,因为我无法写W.class
。是否有其他传递相同信息的方式?
答案 0 :(得分:56)
不允许在类型参数上使用.class
- 由于type erasure,W
在运行时已被删除到Component
。 InputField
还需要来自来电者的Class<W>
,例如InputFieldArray
:
public InputField(String labelText, Class<W> clazz)
{
super(new String[] {labelText}, clazz);
}
答案 1 :(得分:8)
由于类型擦除,W可能无法使用。您应该要求将Class<W>
传递给方法。你得到一个类对象,它的泛型确保由于协方差而只传入W
而没有传入子类。
public InputField(String labelText, Class<W> cls)
{
super(new String[] {labelText}, cls);
}
将采用W.class
,但不采用WSubtype.class
。
答案 2 :(得分:7)
如果您使用的是GSON
库,则可以使用T
轻松获取TypeToken
类型。课程文档可用here:
我是这样做的:
这是我的班级定义:
public class ManagerGeneric <T> {}
这是我的方法:
// Get the type of generic parameter
Type typeOfT = new TypeToken<T>(){}.getType();
// Deserialize
T data = gson.fromJson(json, typeOfT);