在使用通用性时,我在java中遇到了一个小问题。我有一个班级A
:
public class A<T>
在A
的方法中,我需要获取T
的类型名称。
有没有办法使用s
找到字符串T
?
(如果我创建A<String> temp = new A<String>();
,我希望能够在某一时刻获得java.lang.String
- 我必须使用通用性,因为我的某个方法必须返回List<T>
)
这似乎很容易,但我不知道该怎么做。
答案 0 :(得分:41)
由于类型删除,您通常无法执行此操作 - 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
这样的东西。这是有效的,因为用于指定超类的type参数不会被删除。所以你可以这样做:
A<String> a = new A<String>() {};
a
现在指的是A<String>
的子类,因此通过获取a.getClass().getSuperClass()
,您最终可以返回String
。但这太可怕了。
答案 1 :(得分:23)
您可以从子类中获取泛型的名称。看这个例子。 我们定义这样一个父类:
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());
}
}
您可以在main方法或任何实例方法中看到,我能够获取泛型类型的名称,在这种情况下,main将打印: java.lang.Integer
答案 2 :(得分:9)
简短回答:不可能。
稍微长一点的答案:编译代码后,类型参数将被丢弃。 因此,Java无法知道你在那里设置了什么。 但是,您可以将有问题的类传递给您的对象并对其进行操作:
public class A<T> {
private final clazz;
A(Class<T> clazz){
this.clazz = clazz;
}
...
}
答案 3 :(得分:5)
只要通过A:
的子类指定type参数,这当然是可能的public class B extends A<String> {}
Class<?> typeArg = TypeResolver.resolveRawArgument(A.class, B.class);
assert typeArg == String.class;
TypeResolver可通过TypeTools获得。
答案 4 :(得分:1)
Java中的泛型是通过擦除实现的,所以不,你将无法获得在运行时用于创建泛型集合的“类型”的名称。另外,为什么不检查元素以了解它属于哪种类型?
答案 5 :(得分:1)
如果你在一个子类中进行它,它的父类定义了泛型类型,那么这对我有用:
// 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”类,这对我来说毫无用处。
答案 6 :(得分:1)
通常情况下,Apache有一个使用TypeUtils的解决方案:
上述问题的一个简单例子:
TypeUtils.getTypeArguments(temp.getClass(), A.class).get(A.class.getTypeParameters()[0])
免责声明:我没有先尝试构建此版本,但过去曾以类似的方式使用此实用程序。