Reputation: 13161
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
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
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
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