在使用泛型时,我在Java中遇到了一个小问题。我有一个类A
:
public class A<T>
在
A
方法中,我需要获取T
的类型名称。是否有一种方法可以使用T
查找字符串s
?(如果我创建了
A<String> temp = new A<String>();
,我希望能够在某个时候获取java.lang.String
- 我必须使用泛型,因为我的其中一个方法将返回List<T>
)。这似乎很容易,但我不知道如何做到这一点。
在使用泛型时,我在Java中遇到了一个小问题。我有一个类A
:
public class A<T>
A
方法中,我需要获取T
的类型名称。是否有一种方法可以使用T
查找字符串s
?A<String> temp = new A<String>();
,我希望能够在某个时候获取java.lang.String
- 我必须使用泛型,因为我的其中一个方法将返回List<T>
)。由于类型擦除,通常情况下无法做到这一点 - 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
}
然后:
A<String> x = new A<String>(String.class);
这很丑,但这就是类型擦除所造成的:(
另一种选择是使用像Guice的TypeLiteral
这样的东西。这种方法可以工作是因为用于指定超类的类型参数不会被擦除。因此你可以这样做:
A<String> a = new A<String>() {};
a
现在指向A<String>
的一个子类,因此通过获取a.getClass().getSuperClass()
,最终可以回到String
。但这样做非常糟糕。
您可以从子类获取泛型的名称。请参见此示例。我们像这样定义一个父类:
public class GetTypeParent<T> {
protected String getGenericName()
{
return ((Class<T>) ((ParameterizedType) 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());
}
}
你可以看到在主方法或任何实例方法中,我都能获取泛型类型的名称,在这种情况下,主方法将打印:java.lang.Integer。
String
才能获得String
返回。问题不是尝试找到通用参数的值吗? - mike rodent简短回答:不可能。
略微详细的解答:一旦你的代码编译完成,类型参数就会被丢弃。因此,Java无法知道您设置了什么。但是,您可以将相关的类传递给对象并对其进行操作:
public class Example<T> {
private final Class<T> clazz;
public Example(Class<T> clazz){
this.clazz = clazz;
}
...
}
class Foo implements List<Integer>
,那么你就可以得到泛型类型。但是,如果你像 List<Integer> foo;
这样做,由于类型擦除,你是无法得到泛型类型的。并非所有的泛型类型都被擦除了,它取决于你对泛型的使用方式。 - searchengine27TypeUtils.getTypeArguments(temp.getClass(), A.class).get(A.class.getTypeParameters()[0])
TypeUtils
,所以感谢您的提醒。但是目前在我的情况下它无法运行:A.class
出现了错误,“类型参数A的非法类字面量”...我会继续探索/尝试使用TypeUtils
... - mike rodentParameterizedType
。我也看了乔纳森的答案和恩里科·格林的答案。但是,即使使用Apache,直接从实例中获取通用类型(OP的问题)似乎也是不可能的。除非你能告诉我怎么做! - mike rodent// 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 ", ""))
我不能使用#getClass()
而不是#toString()
的原因是,我总是得到“Class”类,这对我没有用。