如何获取泛型类的对象类型?
问题描述:
所以我有以下的通用类:如何获取泛型类的对象类型?
public class Member<T> {
private T id;
private T complexityLevel;
//constructor
public Member(T id, T complexityLevel) {
this.id = id;
this.complexityLevel = complexityLevel;
}
public T getId() {
return id;
}
public T getComplexity() {
return complexityLevel;
}
public void setComplexity(T complexityLevel) {
this.complexityLevel = complexityLevel;
}
public void setId(T id) {
this.id = id;
}
public static void main(String[] args) {
Member<String> mString = new Member<String>("id1", "High");
System.out.printf("id before setting id: %s%n", mString.getId());
mString.setId("id2");
System.out.printf("id after setting id: %s%n", mString.getId());
System.out.printf("complexity before setting it: %s%n", mString.getComplexity());
mString.setComplexity("Low");
System.out.printf("complexity after setting it: %s%n", mString.getComplexity());
// now for an integer
Member<Integer> mInteger = new Member<Integer>(1, 100);
System.out.printf("id before setting id: %d%n", mInteger.getId());
mInteger.setId(2);
System.out.printf("id after setting id: %d%n", mInteger.getId());
// for Double
Member<Double> mDouble = new Member<Double>(100.0);
...
我试图获得Member
类的对象基本类型(String
,Integer
,Double
等)。到目前为止,我有这一点,但问题是它返回"Member"
:
System.out.println(mString.getClass().getName());
System.out.println(mInteger.getClass().getName());
System.out.println(mDouble.getClass().getName());
答
你不能在运行时确定泛型类型,由于type erasure。为了使这种信息擦除之后保存,Member<T>
需要采取在其构造器一个Class<T>
对象,并抓住它:
public class Member<T> {
public final Class<T> type;
private T id;
private T complexityLevel;
//constructor
public Member(T id, T complexityLevel, Class<T> type) {
id = id;
this.complexityLevel = complexityLevel;
this.type = type;
}
再后来:
Member<String> mString = new Member<String>("id1", "High", String.class);
...
System.out.println(mString.type.getName());
另外,如果id
保证从不是null
,您可以使用反射来检索代表其类型的对象Class
:
System.out.println(mString.getId().getClass().getName());
当然getClass()将返回Class<? extends T>
。因此,如果id
实际上是T
的子类,那么您将获得该类的名称,而不是名称T
。
答
该信息(泛型类型T)在编译(类型擦除)过程中被剥离。
使用super type tokens是一种适度疼痛的技术,可以在这里应用。 Guice的TypeLiteral就是一个例子。
另外,String和Integer不是原始类型。 “int”是一个原语。
谢谢。我得到“java.lang.String”,“java.lang.Integer”和“java.lang.Double”。我可以用它来获取子字符串。基本上我需要确定我正在执行的测试用例的参数类型。 – nabsATX
@neal_fazio - 你问如何得到“字符串”,“整数”等?你可以使用'getSimpleName()'而不是'getName()'。 –
完美。我想我需要熟悉一些更多的Java API。 – nabsATX