如何从泛型类型参数中获取`.class`属性?

时间:2013-08-15 14:40:44

标签: java generics

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。是否有其他传递相同信息的方式?

3 个答案:

答案 0 :(得分:56)

不允许在类型参数上使用.class - 由于type erasureW在运行时已被删除ComponentInputField还需要来自来电者的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);