Reputation: 38643
I am having trouble accessing the runtime type of id
via reflection from MyClass
.
public abstract class AbstractEntity<T> {
@Id
private T id; //I need to access the runtime class of T
}
public class MyClass extends AbstractEntity<Long> {}
I am using java reflection and have access to the id Field
in the superclass.
I tried using:
field.getGenericType()
: which returns TypeVariableImpl
with a value T
.field.getType()
which returns Object
.I want to access Long
as the field type.
I am writing a library for others to use and there are a few issues:
@id
. Here is the method I am using to get hold of all fields in the class hierarchy.
private Set<Field> getAllFields(final Object object) {
final Set<Field> fields = new HashSet<>();
fields.addAll(Arrays.asList(object.getClass().getDeclaredFields()));
Class<?> superclass = object.getClass().getSuperclass();
while (superclass != null) {
fields.addAll(Arrays.asList(superclass.getDeclaredFields()));
superclass = superclass.getSuperclass();
}
return fields;
}
I then filter this list for field annotated with @Id
of which there should only be one.
Upvotes: 1
Views: 2450
Reputation: 89199
Generics are not reified at run-time. This means the information is not present at run-time.
One way is to know the class type of the generic parameterized type, i.e., Class<T> entityClass
.
There are couple of ways to achieve this. You can either have a default constructor and reflectively get the class type:
this.entityClass= (Class<T>) ((ParameterizedType) getClass()
.getGenericSuperclass()).getActualTypeArguments()[0];
Or create a constructor, passing the the Generic class type on the constructor:
protected AbstractEntity(Class<T> entityClass) {
this.entityClass = entityClass;
}
Then, your concrete entity class can pass its class type by default, like so:
public class MyClass extends AbstractEntity<Long> {
public MyClass() {
super(Long.class);
}
}
Upvotes: 2