83

这个问题的公认答案描述了如何TGeneric<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. 是否有其他方式传递相同的信息?

4

3 回答 3

67

.class不允许在类型参数上使用 - 因为类型擦除W将在运行时被擦除。还需要从调用者那里获取一个,例如:ComponentInputFieldClass<W>InputFieldArray

public InputField(String labelText, Class<W> clazz)
{
    super(new String[] {labelText}, clazz);
}
于 2013-08-15T14:56:23.640 回答
14

如果您正在使用该GSON库,则可以T使用TypeToken. 类文档可在此处获得:

我是这样做的:

这是我的类定义:

public class ManagerGeneric <T> {}

这是我的方法:

// Get the type of generic parameter
Type typeOfT = new TypeToken<T>(){}.getType();
// Deserialize
T data = gson.fromJson(json, typeOfT);
于 2017-09-11T08:48:59.043 回答
11

由于类型擦除,W 可能不可用。您应该要求将 aClass<W>传递给方法。你得到一个类对象,它的泛型确保只有W子类被传入,因为协方差,没有子类被传入。

public InputField(String labelText, Class<W> cls)
{
    super(new String[] {labelText}, cls);
}

会拿W.class但不会WSubtype.class

于 2013-08-15T14:56:30.477 回答