Java 获取泛型类的泛型参数的类型名称
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6624113/
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
Get type name for generic parameter of generic class
提问by ThR37
I have a small problem in java while using genericity. I have a class A
:
在使用泛型时,我在 java 中遇到了一个小问题。我有一堂课A
:
public class A<T>
In a method of A
, I need to get the type name of T
.
Is there a way to find the string s
using T
?
在 的方法中A
,我需要获取T
. 有没有办法找到字符串s
使用T
?
(If I create A<String> temp = new A<String>();
, I want to be able to get java.lang.String
at one point - I have to use genericity because one of my methods will have to return a List<T>
).
(如果我创建A<String> temp = new A<String>();
,我希望能够java.lang.String
在某一时刻获得- 我必须使用通用性,因为我的方法之一必须返回 a List<T>
)。
This seems quite easy but I do not see how to do it.
这似乎很容易,但我不知道如何去做。
采纳答案by Jon Skeet
You can't do this in general because of type erasure- an instance of A<String>
doesn't knowthe type of T
. If you need it, one way is to use a type literal:
你不能做到这一点,一般是因为类型擦除-实例A<String>
不知道的类型T
。如果需要,一种方法是使用类型文字:
public class A<T>
{
private final Class<T> clazz;
public A<T>(Class<T> clazz)
{
this.clazz = clazz;
}
// Use clazz in here
}
Then:
然后:
A<String> x = new A<String>(String.class);
It's ugly, but that's what type erasure does :(
这很丑陋,但这就是类型擦除的作用:(
An alternative is to use something like Guice's TypeLiteral
. This works because the type argument used to specify a superclassisn't erased. So you can do:
另一种方法是使用类似 Guice 的TypeLiteral
. 这是有效的,因为用于指定超类的类型参数没有被删除。所以你可以这样做:
A<String> a = new A<String>() {};
a
now refers to a subclassof A<String>
, so by getting a.getClass().getSuperClass()
you can eventually get back to String
. It's pretty horrible though.
a
现指子类的A<String>
通过获取,所以a.getClass().getSuperClass()
你最终可以得到回String
。虽然它非常可怕。
回答by Sanjay T. Sharma
Generics in Java are implemented by erasure, so no, you won't be able to get the name of the "type" which was used to create your generic collection at run-time. Also, why not just inspect the elements to know what type it belongs to?
Java 中的泛型是通过擦除实现的,所以不,您将无法获得在运行时用于创建泛型集合的“类型”的名称。另外,为什么不检查元素以了解它属于什么类型?
回答by Urs Reupke
Short answer: Impossible.
简短的回答:不可能。
Slightly longer answer: Once your code is compiled, the type parameters is discarded. Thus, Java cannot know what you set there. You could, however, pass the class in question to your object and operate on it:
稍微长一点的答案:一旦你的代码被编译,类型参数就会被丢弃。因此,Java 无法知道您在那里设置了什么。但是,您可以将有问题的类传递给您的对象并对其进行操作:
public class A<T> {
private final Class<T> clazz;
A(Class<T> clazz){
this.clazz = clazz;
}
...
}
回答by Jonathan
This certainly is possible so long as the type argument is specified via a subclass of A:
只要通过 A 的子类指定类型参数,这当然是可能的:
public class B extends A<String> {}
Class<?> typeArg = TypeResolver.resolveRawArgument(A.class, B.class);
assert typeArg == String.class;
TypeResolver is available via TypeTools.
TypeResolver 可通过TypeTools 获得。
回答by Enrico Giurin
You can get the name of the generics from the subclass. See this example. We Define a parent class like this:
您可以从子类中获取泛型的名称。请参阅此示例。我们像这样定义一个父类:
public class GetTypeParent<T> {
protected String getGenericName()
{
return ((Class<T>) ((ParameterizedType) getClass()
.getGenericSuperclass()).getActualTypeArguments()[0]).getTypeName();
}
}
We then define its child class in this way:
然后我们以这种方式定义它的子类:
public class GetTypeChild extends GetTypeParent<Integer> {
public static void main(String[] args) {
GetTypeChild getTypeChild = new GetTypeChild();
System.out.println(getTypeChild.getGenericName());
}
}
You can see that in the main method, or in any instance method, I am capable to get the name of the generics type, in this case the main will print: java.lang.Integer.
您可以看到在 main 方法或任何实例方法中,我能够获取泛型类型的名称,在这种情况下, main 将打印:java.lang.Integer。
回答by milosmns
If you're doing it in a subclass which has it's parent class defining the generic type, this is what worked for me:
如果您在一个子类中执行此操作,该子类的父类定义了泛型类型,那么这对我有用:
// 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 ", ""))
Reason why I couldn't do it with #getClass()
instead of #toString()
in the first snip is that I was always getting the "Class" class, which is useless to me.
我不能用#getClass()
而不是#toString()
在第一个剪辑中做到这一点的原因是我总是得到“Class”类,这对我来说没用。
回答by Hazok
As is normally the case, Apache has a solution for this one with TypeUtils:
通常情况下,Apache 有一个使用 TypeUtils 的解决方案:
A quick example from the above question:
上述问题的一个简单示例:
TypeUtils.getTypeArguments(temp.getClass(), A.class).get(A.class.getTypeParameters()[0])
Disclaimer: I did not attempt building this first, but have used this utility in a similar fashion in the past.
免责声明:我不是先尝试构建它,而是在过去以类似的方式使用过这个实用程序。