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


70

问题的可接受答案描述了如何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。还有其他传递相同信息的方式吗?


如果发布代码示例(即触发编译器错误的代码示例),您的问题可能会更加清楚。
邓肯·琼斯

但是您必须正确使用类名Skeet<J>吗?您需要将该类传递给Generic构造函数。如果您显示实际代码,我们可以为您提供更好的帮助。
罗希特·贾因

J.class由于类型擦除,您不能使用。但是您可以ClassSkeet<J>施工中获得具体的变量
RiaD

在链接的问题上,乔恩不是字面上的意思T.class-您不能.class在类型参数上使用。他的意思是Class<T>呼叫者需要传递一个。
Paul Bellora

我知道。但是,我希望能够通过J。那可能吗?
约翰·高尔斯

Answers:


63

使用.class一个类型参数是不允许的-因为类型擦除W将被清除,以Component在运行时。InputField还将需要Class<W>从呼叫者那里收取,例如InputFieldArray

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

基于给定的类型擦除链接,泛型将被类型替换,Object因为在这种情况下未给出界限。所以因为typeClass是它的子类Object,所以我认为在这种情况下我们将无法调用.class。但是,如果给定的界限不是Object(例如<? extends Foo>,我的意思.class是在这种情况下,该方法应该仍然可以选择。在这里,我有点困惑。)@Paul Bellora
Dreamer

@Dreamer.class不是一种方法,也不是可以在运行时动态解析的任何方法。这是一个编译时构造,用于静态获取Class表示显式具体类型的对象。
Paul Bellora '17

11

如果您使用的是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);

10

由于类型擦除,W可能不可用。您应该要求将aClass<W>传递到方法中。您会得到一个类对象W,由于协方差,它的泛型确保仅传递子类,而不会传递任何子类。

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

将采取W.class但不是WSubtype.class

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.