Reputation: 10938
I have an abstract class Abstr<T>
and an extending class Ext<T>
. I need Abstr
to know, with which T
its extension was initialized so it can return that type. So far I've done this by giving the type to the constructor and then calling the superconstructor to save it. But this should work with reflections too I think. So far like I said:
public abstract class Abstr<T> {
private Class<T> type;
public Abstr(Class<T> _class) {
this.type = _class;
}
}
public class Ext<T> extends Abstr<T> {
public Ext(Class<T> _class) {
super(_class);
}
}
public void someMethod() {
Ext<String> ext = new Ext<String>(String.class);
}
Using reflections should rid me of calling any constructor as the extending default constructor will call the abstract classes default constructor which should then save the type of the calling constructor:
public Abstr() {
this.type = (Class<D>) this.getClass().getTheTypeParameter(); // something along these lines
}
Thanks!
Upvotes: 0
Views: 1320
Reputation: 88757
This might not always work, since if you just have new Ext<String>()
in some method there's no reflection data for the type.
Thus Ext<String> ext = new Ext<String>(String.class);
would loose the type information at runtime (type erasure) effectively resulting in Ext ext = new Ext(String.class);
.
If you have fields like private Ext<String> stringExt
or concrete subclasses like StringExt extends Ext<String>
you have reflection data you could retrieve.
Here's a short article with some source that you could use to get reflection data for concrete subclasses (and maybe for fields, but I didn't test that): http://www.artima.com/weblogs/viewpost.jsp?thread=208860
As I said, we're using an adjusted version of that code to get type parameters for concrete subclasses.
So we have something like this:
class AbstractDAO<T entityType> {
protected Class<?> entityClass;
protected AbstractDAO() {
//ReflectionUtil is our adjusted version of code in the link above
entityClass = ReflectionUtil.getTypeArguments(AbstractDAO.class, getClass() ).get(0);
}
}
//Here entityClass is User.class
class UserDAO extends AbstractDAO<User> { ... }
Upvotes: 1
Reputation: 533880
The generic type of Abstr is T
This all you can get via reflection.
If you want to simplify your code you can write.
public class Ext<T> extends Abstr<T> {
protected Ext(Class<T> _class) {
super(_class);
}
public static <T> Ext<T> of(Class<T> _class) { return new Exit<T>(_class); }
}
Ext<String> ext = Ext.of(String.class);
Upvotes: 1
Reputation: 8523
The only case when it works is when you have a non-generic class with a generic parent. An example would be,
class Trick<T> {
T t;
}
public class GenericTest {
public static void main(String[] args) {
Trick<Set<String>> trick = new Trick<Set<String>>() {
};
// Prints "class org.acm.afilippov.GenericTest$1"
System.out.println(trick.getClass());
// Prints "org.acm.afilippov.Trick<java.util.Set<java.lang.String>>"
System.out.println(trick.getClass().getGenericSuperclass());
}
}
For further reading refer to the Reflecting generics tutorial — the answer is there, but it's way too long to quote it and not feel as if I was stealing a code. So please read there :)
Upvotes: 3
Reputation: 36621
If you really need a method in Abstr
similar to
public Class<T> getType()
you have no choice but to pass the Class
isntance in the constructor (or in any other method). You cannot retrieve the Class
of T
due to type erasure, which basically comes down to the fact that T
is not available at runtime, only at compile time.
Upvotes: 1