简体   繁体   中英

Why generic type lookup is not allowed at runtime in Java?

I am trying to see if it possible to get object type for a generic class at run-time in Java.

Example:

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
}

Testing..

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());
        }
    }
}

Is it possible to get wrapper classes ( String , Integer , Double etc) for objects of Member class at run-time?

You can't determine generic types at runtime due to type erasure . In order for this information to be preserved after erasure, Member<T> would need to take a Class<T> object in its contructor and hold onto it:

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;
}

Then later:

Member<String> mString = new Member<String>("id1", "High", String.class);

...

System.out.println(mString.type.getName());

Alternatively, if id is guaranteed never to be null , you could use reflection to retrieve the Class object representing its type:

System.out.println(mString.getId().getClass().getName());

Of course getClass() will return a Class<? extends T> Class<? extends T> . So if id is in fact a subclass of T , you're going to get the name of that class rather than the name of T .

This information (the generic type T) is stripped out during compilation (type erasure).

Using super type tokens is a moderately painful technique that can apply here. Guice's TypeLiteral is an example of this.

Also, String and Integer are not primitive types. "int" is a primitive.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM