在使用泛型时,java中存在一个小问题。我有一个类A
:获取泛型类的泛型参数的类型名称
public class A<T>
在A
的方法,我需要得到的T
类型名称。 有没有办法找到字符串s
使用T
? (如果我创建A<String> temp = new A<String>();
,我希望能够得到java.lang.String
在一个点 - 我必须使用泛型,因为我的方法之一将不得不返回List<T>
)。
这似乎很容易,但我不知道该怎么做。
非常感谢您的帮助。
在使用泛型时,java中存在一个小问题。我有一个类A
:获取泛型类的泛型参数的类型名称
public class A<T>
在A
的方法,我需要得到的T
类型名称。 有没有办法找到字符串s
使用T
? (如果我创建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
。虽然这很可怕。
Java中的泛型是通过擦除来实现的,所以不会,您将无法获得用于在运行时创建泛型集合的“类型”的名称。另外,为什么不只是检查元素以知道它属于哪种类型?
其实我不能,因为我在开始时没有任何T的实例。该对象实现了一个osgi Service Listener,我想用我的接口名称来过滤bundle消息。之后我才得到实例。 – ThR37
简答:不可能。
稍微长一点的答案:编译代码后,类型参数将被丢弃。因此,Java不知道你在那里设置了什么。 你可以,但是,通过有问题的类的对象,并对其进行操作:
public class A<T> {
private final clazz;
A(Class<T> clazz){
this.clazz = clazz;
}
...
}
这肯定是答案。由于*擦除*(这是我经常听到的一个术语,但其操作我从未完全深入分析),因此永远不能使用通用参数作为“走私”额外参数。相反,使用常规参数。似乎很奇怪的是,这些信息永远无法获得,我不清楚这是设计选择还是不可避免的... –
这当然是可能的,只要指定类型参数通过A的子类:
public class B extends A<String> {}
Class<?> typeArg = TypeResolver.resolveRawArgument(A.class, B.class);
assert typeArg == String.class;
TypeResolver可通过TypeTools获得。
我真的希望这可以提供答案并获得代码。但是我不能做OP想要做的事情:从“实时”创建的A实例中获取泛型参数,即不实际创建子类。我认为这是不可能的... –
您可以从子类中获得泛型的名称。看到这个例子。 我们定义了一个父类是这样的:
public class GetTypeParent<T> {
protected String getGenericName()
{
return ((Class<T>) ((ParameterizedType) getClass()
.getGenericSuperclass()).getActualTypeArguments()[0]).getTypeName();
}
}
然后,我们用这种方式定义它的子类:
public class GetTypeChild extends GetTypeParent<String> {
public static void main(String[] args) {
GetTypeChild getTypeChild = new GetTypeChild();
System.out.println(getTypeChild.getGenericName());
}
}
你可以看到,在主要方法,或以任何实例方法,我能够获得泛型类型的名称,在这种情况下,main将打印:java.lang.String。
...并且你得到子类的名字(如果有的话)。太好了! –
这看起来确实很聪明......但是你必须“硬编码”类型'String'才能得到'String'。是不是试图找到泛型参数的值的问题? –
我不认为这有帮助。子类已经知道该类型,因为它是硬编码的:String。调用父级的方法来获取它是没有用的。不幸的是,它不是一个有用的用例,它不是一个有用的用例,而且它不像@mikeodent –
如果你在它有它的定义泛型类型父类的子类这样做,这是对我工作:
// 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()
在第一个剪辑中,我总是得到“阶级”班,这对我来说毫无用处。
由于通常是这种情况,Apache的具有用于这一个与TypeUtils的溶液:
从上述问题一个简单的例子:
TypeUtils.getTypeArguments(temp.getClass(), A.class).get(A.class.getTypeParameters()[0])
声明:我没有试图首先构建,但过去曾以类似的方式使用该实用程序。
Apache Commons的粉丝,从来没有听说过'TypeUtils',所以谢谢......但是目前这对我不起作用:'A.class'给出的错误是“类型参数A的非法类文字”。 。只是要用'TypeUtils'做一些探索/实验...... –
@mike啮齿动物这个对我来说很有用,当我用它在分水岭和不同类型的多个类中移动时通过水线。你有没有可用的例子吗? – Hazok
后来:不行,不能得到这个工作。不知道如何首先获得'ParameterizedType'。还看了Jonathan的回答和Enrico Guerin的回答。但是从实例直接获取泛型类型(OP的问题)似乎是不可能的,即使对于Apache也是如此。除非你能告诉我如何! –
看到这个问题http://stackoverflow.com/questions/3403909/get-generic-type-of-class-at-runtime –