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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18255117/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 23:45:56  来源:igfitidea点击:

How do I get the `.class` attribute from a generic type parameter?

javagenerics

提问by John Gowers

The accepted answer to this questiondescribes how to create an instance of Tin the Generic<T>class. This involves passing in a Class<T>parameter to the Genericconstructor and callin the newInstancemethod from that.

这个问题的公认答案描述了如何TGeneric<T>类中创建一个实例。这涉及将Class<T>参数传递给Generic构造函数并newInstance从中调用方法。

A new instance of Generic<Bar>is then created, and the parameter Bar.classis passed in.

Generic<Bar>然后创建一个新实例,并Bar.class传入参数。

What do you do if the generic type parameter for the new Genericclass is not some known class like Barbut is itself a generic type parameter? Suppose I had some other class Skeet<J>and I wanted to create a new instance of Generic<J>from inside that class. Then, if I try to pass in J.classI get the following compiler error:

如果新Generic类的泛型类型参数不是某个已知类,Bar但它本身就是泛型类型参数,你会怎么做?假设我有一些其他类,Skeet<J>并且我想Generic<J>从该类内部创建一个新实例。然后,如果我尝试传入,则会J.class出现以下编译器错误:

cannot select from a type variable.

Is there any way around this?

有没有办法解决?

The specific bit of code triggering the error for me is:

对我来说触发错误的特定代码是:

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();
      /* ... */
    }
    /* ... */
  }
  /* ... */
}

The error happens, because I can't write W.class. Is there some other way of passing in the same information?

错误发生了,因为我不能写W.class. 是否有其他方式传递相同的信息?

采纳答案by Paul Bellora

Using .classon a type parameter isn't allowed - because of type erasure, Wwill have been erasedto Componentat runtime. InputFieldwill need to also take a Class<W>from the caller, like InputFieldArray:

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

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

回答by nanofarad

W may not be available due to type erasure. You should require that a Class<W>is passed into the method. You get a class object and its generic ensures that only Wand no subclass is passed in, due to covariance.

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

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

will take W.classbut not WSubtype.class.

W.class但不会WSubtype.class

回答by jdex

If you're using the GSONlibrary, you can get the type of Teasily by using TypeToken. The class documentation is available here:

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

I did it like this:

我是这样做的:

This is my class definition:

这是我的类定义:

public class ManagerGeneric <T> {}

This is in my method:

这是我的方法:

// Get the type of generic parameter
Type typeOfT = new TypeToken<T>(){}.getType();
// Deserialize
T data = gson.fromJson(json, typeOfT);