Priyank Doshi
Priyank Doshi

Reputation: 13161

Get Generic Type in Constructor in java

Is there a way to find generic type in constructor?

 public class geneticarg {
    public static void main(String[] args) {
    a<String> a1 = new a<String>("a");
    a<String> a2 = new a<String>(null); // gives NPE
    System.out.println(a1.getClazz());
    }
}

class a<T> {

private Class<T> clazz;
private T element;

public a(T clazz) {
this.clazz = (Class<T>) clazz.getClass();
this.element = clazz;
// what if clazz is null ?

}
//getter and setter
}

EDIT : It is not necessary that always String comes.

Upvotes: 2

Views: 7352

Answers (3)

Peter Lawrey
Peter Lawrey

Reputation: 533880

You have to pass the type in the constructor. You can use a static factor to avoid having to set it twice.

A<String> a1 = A.wrap("a");
A<String> a2 = A.forClass(String.class);

class A<T> {
    private final Class<T> clazz;
    private final T element;

    private A(T t, Class<T> clazz) {
        this.clazz = clazz;
        this.element = t;
    }

    public static <T> A<T> wrap(T t) {
        return new A<T>(t, (Class) t.getClass());
    }

    public static <T> A<T> forClass(Class<T> clazz) {
        return new A<T>(null, clazz);
    }

    //getter and setter
}

Upvotes: 4

Bohemian
Bohemian

Reputation: 425418

Peter is quite correct. I'd like to add some more info:

The instance of Class<T> passed into the constructor is called a type token.

Upvotes: 1

hoaz
hoaz

Reputation: 10171

The only way to avoid type erasure in your case is to use generic superclass. You need to subclass your generic type and then you can access parametrized type, it is available via reflection API:

public abstract class a<T> {

    private Class<T> clazz;
    private T element;

    public a(T obj) {
        ParameterizedType type = (ParameterizedType) this.getClass().getGenericSuperclass();
        this.clazz = (Class<T>) type.getActualTypeArguments()[0];
        this.element = obj;
    }
}

class StringA extends a<String> {
    public StringA(String obj) {
        super(obj);
    }
}

Upvotes: 3

Related Questions