Reputation: 1933
I have a generic repository class that looks like this:
public class HibernateRepository<E extends Object, EId>
implements EntityRepository<E, EId> {
// Many things that are working fine
@Override
public E getById(EId id) {
return entityManager.getReference(E.class, id); // <<< Error here!
}
}
The method getById()
is supposed to return a certain entity instance given its Id
. Something very trivial in many other situations, but not in this one, since the compiler returns:
Illegal class literal for the type parameter E
Notice that I don't want to pass the desired class to the method, since I already did that in the class definition.
The usage for this class could be:
public class MyClassRepositoryHibernate
extends HibernateRepository<MyClass, Long> {
}
Now this new repository works on MyClass
instances and the Id
is typed with Long
.
Is that possible in Java?
Upvotes: 0
Views: 2614
Reputation: 11818
The type will be erased after compilation and thus is not available. This is called Type Erasure. You have to pass the Class object somewhere.
Upvotes: 1
Reputation: 21184
You will have to pass the actual class type to the constructor of your HibernateRepository
and use that throughout your methods. The JVM has no knowledge of what "E" is at runtime hence you need to provide the concrete class type.
You can ensure you don't instantiate the object incorrectly by using the Generic parameter type in the constructor, like this:
public class HibernateRepository<E extends Object, EId>
implements EntityRepository<E, EId> {
private Class<E> clazz;
public HibernateRepository(Class<E> clazz) {
this.clazz = clazz;
}
@Override
public E getById(EId id) {
return entityManager.getReference(clazz, id); // <<< Error here!
}
}
A pain, but a necessity due to type erasure.
Upvotes: 2