Java 当泛型类型没有参数时,如何获取泛型类型的类?

Java 当泛型类型没有参数时,如何获取泛型类型的类?,java,generics,Java,Generics,我刚知道这件事 现在,如果我以这种方式编码一个泛型类型没有出现在参数列表中的方法,那么有没有办法访问变成T的实际类 我是说,到目前为止,我编写相同代码的方法是 private <T> T get(String key, Class<T> clazz) { // here I can do whatever I want with clazz, e.g.: return clazz.cast(value); } 但这给了我一个常见的警告类型安全:未选中从对象到T的

我刚知道这件事

现在,如果我以这种方式编码一个泛型类型没有出现在参数列表中的方法,那么有没有办法访问变成
T
的实际类

我是说,到目前为止,我编写相同代码的方法是

private <T> T get(String key, Class<T> clazz) {
  // here I can do whatever I want with clazz, e.g.:
  return clazz.cast(value);
}
但这给了我一个常见的警告
类型安全:未选中从对象到T的强制转换。好的,
@SuppressWarnings(“unchecked”)
在这里很有帮助,但实际上我想对方法的预期返回类型做一些事情。如果我添加一个局部变量

T retValue;
我必须用一些东西初始化它,
null
没有帮助。在我指定它之后

@SuppressWarnings("unchecked")
T retValue = (T) value;
我能做到

retValue.getClass().getName()
但是,如果强制转换失败,我就再也没有关于
T
的信息了

由于Java(或者至少我的Java6)在运行时不再具有通用信息,所以我目前想不出一种方法来实现这一点。有办法吗?还是我必须坚持我的“旧”方法


请注意,我列出的示例非常简单,没有多大意义。我想在这里做更复杂的事情,但这超出了范围。

正如您所提到的,Java泛型只在构建时使用。它们不在运行时使用


因此,您使用的旧方法将是实现此目标的唯一方法。

不幸的是,您不能。所有泛型和类型参数在运行时都会被删除。因此,在运行时,
T
的类型只是
对象
retValue.getClass().getName()
将始终返回对象的运行时类型,而不是参数类型的类名


如果您想获取参数类,除了使用第一个解决方案外,没有其他方法。(也就是说,显式地传递类对象。)

如果希望在运行时使用泛型类型,则需要将其作为字段或为特定类型组合创建类型的子类

e、 g


我发现从T获得
Class
有一个解决方案:

public class Action<T>{
}

public Class<?> getGenericType(Object action) throws ClassNotFoundException{
   Type type =
   ((ParameterizedType)action.getClass().getGenericSuperclass())
      .getActualTypeArguments()[0];
   String sType[] = type.toString().split(" ");

   if(sType.length != 2)
      throw new ClassNotFoundException();

   return Class.forName(sType[1]);
}
公共集体诉讼{
}
公共类getGenericType(对象操作)引发ClassNotFoundException{
类型类型=
((ParameterizedType)action.getClass().getGenericSuperclass())
.getActualTypeArguments()[0];
字符串sType[]=type.toString().split(“”);
如果(sType.length!=2)
抛出新的ClassNotFoundException();
返回类.forName(sType[1]);
}
以上代码的用法:

Action<String> myAction = new Action<String>();

getGenericType(myAction);
Action myAction=newaction();
getGenericType(myAction);
我没有用基元类型(int、byte、boolean)测试这一点

我认为它不是很快,但您不必将
Class
传递给构造函数

编辑:


上面的用法不正确,因为泛型超类不可用于
操作
。泛型超类将仅适用于继承类,如
类ActionWithParam扩展操作{}
。这就是我改变主意的原因,现在我建议也将类参数传递给构造函数。感谢您的更正。

您是对的,这将是我不希望发生的另一个副作用。看起来像是@NitzanVolman的复制品:在某种程度上,您是对的,但并不完全正确。同意,我有几种方法,如
private t get(String key,Class clazz)
就是因为这个。你不能得到类的泛型类型,但可以得到超类(和超接口)的类型@PeterLawrey:哇,谢谢。但是,如果我使用
List List=newarraylist(){}它不工作
getActualTypeArguments()[0]
是一个
sun.reflect.generics.reflectiveObjects.TypeVariableImpl
。这有意义吗?您可以打印
list.getClass()
?我怀疑它的ArrayList在你的案例中。@PeterLawrey:是的,它打印
类testpkg.GenTest$1
。这就是新的内联类。但是,是的,因为它是子类化的,所以它是一个
ArrayList
。除非您使用实类型构造原始集合,否则它不会有实参数类型。怎么了?我知道((ParameterizedType)action.getClass().getGenericSuperclass()).getActualTypeArgum中应该有长度检查和迭代‌​ents()和sType[0]与“class”的比较。我在我的自定义远程方法调用中使用了它,它可以正常工作。如果有其他错误,请给我一些提示。我复制了我示例中错误的部分。我已经测试了代码的类似部分,发现它只适用于继承类(类示例扩展操作),而不适用于直接泛型类(新操作)。
retValue.getClass().getName()
List<String> list = new ArrayList<String>() {}; // creates a generic sub-type
final Class type = (Class) ((ParameterizedType) list.getClass()
                            .getGenericSuperclass()).getActualTypeArguments()[0];
System.out.println(type);
class java.lang.String
public class Action<T>{
}

public Class<?> getGenericType(Object action) throws ClassNotFoundException{
   Type type =
   ((ParameterizedType)action.getClass().getGenericSuperclass())
      .getActualTypeArguments()[0];
   String sType[] = type.toString().split(" ");

   if(sType.length != 2)
      throw new ClassNotFoundException();

   return Class.forName(sType[1]);
}
Action<String> myAction = new Action<String>();

getGenericType(myAction);