Java 获取泛型类的泛型参数的类型名称

Java 获取泛型类的泛型参数的类型名称,java,generics,Java,Generics,我在java中使用泛型时遇到了一个小问题。我有一门课a: public class A<T> 公共A类 在a的方法中,我需要获取T的类型名。 有没有办法使用T查找字符串s (如果我创建A temp=newa();,我希望能够在某一点上获得java.lang.String——我必须使用泛型,因为我的一个方法必须返回列表) 这似乎很容易,但我不知道如何做。由于类型擦除的原因,您一般不能这样做-一个A的实例不知道t的类型。如果需要,一种方法是使用类型文字: public class A

我在java中使用泛型时遇到了一个小问题。我有一门课
a

public class A<T>
公共A类
a
的方法中,我需要获取
T
的类型名。 有没有办法使用
T
查找字符串
s

(如果我创建
A temp=newa();
,我希望能够在某一点上获得
java.lang.String
——我必须使用泛型,因为我的一个方法必须返回
列表


这似乎很容易,但我不知道如何做。

由于类型擦除的原因,您一般不能这样做-一个
A
的实例不知道
t
的类型。如果需要,一种方法是使用类型文字:

public class A<T>
{
    private final Class<T> clazz;

    public A<T>(Class<T> clazz)
    {
        this.clazz = clazz;
    }

    // Use clazz in here
}

a
现在指的是
a
的一个子类,因此通过获取
a.getClass().getSuperClass()
最终可以返回到
字符串。但是这非常可怕。

Java中的泛型是通过擦除实现的,因此,不,您将无法获得在运行时用于创建泛型集合的“类型”的名称。此外,为什么不检查元素以了解它属于哪种类型?

简短回答:不可能

稍长一点的回答:编译代码后,类型参数将被丢弃。 因此,Java无法知道您在那里设置了什么。 但是,您可以将有问题的类传递给对象并对其进行操作:

public class Example<T> {
  private final Class<T> clazz;

  public Example(Class<T> clazz){
     this.clazz = clazz;
  }
...
}
公共类示例{
私人期末班;
公共示例(类clazz){
this.clazz=clazz;
}
...
}

只要类型参数是通过

public class B extends A<String> {}

Class<?> typeArg = TypeResolver.resolveRawArgument(A.class, B.class);
assert typeArg == String.class;
公共类B扩展了{}
Class typeArg=TypeResolver.resolveRawArgument(A.Class,B.Class);
断言类型arg==String.class;

TypeResolver可通过。

从子类中获取泛型的名称。看看这个例子。 我们定义这样的父类:

public class GetTypeParent<T> {

    protected String getGenericName()
    {
        return ((Class<T>) ((ParameterizedType) getClass()
                .getGenericSuperclass()).getActualTypeArguments()[0]).getTypeName();
    }
}
公共类GetTypeParent{
受保护的字符串getGenericName()
{
返回((类)((ParameteredType)getClass()
.getGenericSuperclass()).getActualTypeArguments()[0]).getTypeName();
}
}
然后,我们用以下方式定义其子类:

public class GetTypeChild extends GetTypeParent<Integer> {
    public static void main(String[] args) {
        GetTypeChild getTypeChild = new GetTypeChild();
        System.out.println(getTypeChild.getGenericName());
    }
}
public类GetTypeChild扩展了GetTypeParent{
公共静态void main(字符串[]args){
GetTypeChild GetTypeChild=新建GetTypeChild();
System.out.println(getTypeChild.getGenericName());
}
}

您可以看到,在main方法或任何实例方法中,我都能够获得泛型类型的名称,在本例中,main将打印:java.lang.Integer。

如果您在一个子类中执行此操作,而该子类的父类定义了泛型类型,这对我来说是有效的:

// get generic type class name
String name = ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0].toString();

// then when you've got the name, you can make the Class<T> object
Class.forName(name.replace("class ", ""))
//获取泛型类型类名
字符串名称=((ParameterizedType)getClass().getGenericSuperclass()).getActualTypeArguments()[0].toString();
//然后,当您获得名称后,就可以使类对象
Class.forName(name.replace(“Class”,“”)

在第一个剪贴中,我不能用
#getClass()
而不是
#toString()
来完成它的原因是,我总是得到“Class”类,这对我来说是无用的。

通常情况下,Apache有一个使用TypeUtils的解决方案:

上述问题的一个简单示例:

TypeUtils.getTypeArguments(temp.getClass(), A.class).get(A.class.getTypeParameters()[0])

免责声明:我没有首先尝试构建此工具,但在过去以类似的方式使用过此工具。

看到这个问题实际上我看不到,因为我在开始时没有任何t的实例。该对象实现了一个osgi服务侦听器,我想用我的接口名过滤bundles消息。我只在那之后得到实例……然后你得到子类的名称(如果有的话)。美好的这看起来真的很聪明。。。但是您必须输入“硬编码”类型
String
,才能返回
String
。问题不在于试图找到泛型参数的值吗?我认为这没有帮助。子类已经知道该类型,因为它是硬编码的:String。调用父对象的方法来获取它是没有用的。不幸的是,这不是一个有用的用例,也不是@MikCorventit已经提到的OP所要求的,如果您想在运行时知道类型是什么,例如,如果您有一组从公共超类继承的类。@MikCorventit否,getGenericName()返回子类中T的真实类型,在本例中为java.lang.Integer。在T为java.lang.String之前,我更改了这个示例,所以它可能会让人困惑。Apache Commons的忠实粉丝,从未听说过
TypeUtils
,所以谢谢。。。但这目前对我不起作用:
A.class
给出了一个错误“类型参数A的非法类文本”。。。我只是想用
TypeUtils
…@mike啮齿动物做一些探索/实验,当我在继承人制度中使用它时,它对我很有用,并且在继承人制度中使用了不同数量的类型。你有没有一个不起作用的例子?后来:没有,不能让它起作用。首先不确定如何获取
参数化类型。还看了乔纳森和恩里科·盖林的答案。但是直接从实例获取泛型类型(OP的问题)似乎是不可能的,即使对于Apache也是如此。除非你能告诉我怎么做!我真的希望这能提供答案并掌握代码。但是我不能做OP想要做的事情:从一个“动态”创建的实例中获取泛型参数,也就是说,在没有实际生成子类的情况下。我想这是不可能的…这肯定是答案。由于擦除(这是我经常听到的一个术语,但我从来没有对其工作原理进行过深入的分析),因此您永远不能将泛型参数用作“偷偷引入”的额外参数。相反,请使用常规参数。这似乎很奇怪
// get generic type class name
String name = ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0].toString();

// then when you've got the name, you can make the Class<T> object
Class.forName(name.replace("class ", ""))
TypeUtils.getTypeArguments(temp.getClass(), A.class).get(A.class.getTypeParameters()[0])