Java中是否允许在运行时进行泛型类型查找?

时间:2011-10-06 06:07:39

标签: java generics type-erasure

我试图在Java中运行时获取泛型类的对象类型。

示例:

public class Member<T> {

    private T id;
    private T complexityLevel;

    // constructor
    public Member(T id, T complexityLevel) {
        this.id = id;
        this.complexityLevel = complexityLevel;
    }

    // getters and setters goes here
}

测试..

public class TestDrive {

    public static void main(String[] args) {
        Member<String> memberString = new Member<String>("1", "100");
        Member<Integer> memberInteger = new Member<Integer>(1, 100);
        Member<Double> memberDouble = new Member<Double>(1.0, 100.00);

        List<Member<?>> members = new ArrayList<>();
        members.add(memberString);
        members.add(memberInteger);
        members.add(memberDouble);

        for (Member<?> aMember : members) {
            if (aMember.getClass().isInstance(String.class))
                System.out.printf("String member is found with id: " + aMember.getId());
            else if (aMember.getClass().isInstance(Integer.class))
                System.out.printf("Integer member is found with id: " + aMember.getId());
            else if (aMember.getClass().isInstance(Double.class))
                System.out.printf("Double member is found with id: " + aMember.getId());
        }
    }
}

是否可以在运行时为String类的对象获取包装类(IntegerDoubleMember等?

2 个答案:

答案 0 :(得分:3)

由于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的名称。

答案 1 :(得分:3)

此信息(通用类型T)在编译期间被删除(类型擦除)。

使用super type tokens是一种适用于此的适度痛苦技巧。 Guice的TypeLiteral就是一个例子。

此外,String和Integer不是原始类型。 “int”是一个原语。