This is probably a very basic question, but I'm really new to generics in Java and I'm having a hard time altering my thought process from the way things are done in C#, so bear with me.
I'm trying to build a generic repository in Java. I've created an IRepository interface that looks like this:
public interface IRepository<T extends IEntity>
And a Repository class that looks like this:
public class Repository<T extends IEntity> implements IRepository<T>
Now, from within the constructor of my Repository class, I'd like to be able to "divine" the exact type of T. For example, if I instantiated a repository like this:
IRepository<MyClass> repo = new Repository<MyClass>();
I'd like to know that T is actually MyClass. This is trivial in C#, but obviously generics are a totally different beast in Java and I can't seem to find anything that would help me do this.
Java uses type erasure, so the specific information is lost at runtime - you only know that this type is generic, not what's the specific argument you've supplied at compile time.
You can always add the actual type of T in your constructor, like so:
public class Repository<T> implements IRepository<T>
public Repository(Class<T> type) {
}
}
and instantiate like
IRepository<MyClass> repo = new Repository<MyClass>(MyClass.class);
I've done something similar (also to implement a Repository/Registry pattern) and with a bit of work you can actual find out the type. Note however I wasn't doing this with interfaces, but with a base class, and also note that it took a bit of trial and error to arrive at a solution that worked. This code was running on the Sun JVM so it may be that I've stumbled into an area that is JVM specific.
Also - as another comment mentioned, just because you can do this, doesn't mean you necessarily should :)
import java.lang.reflect.ParameterizedType;
...
public static Class<?> type(Object target) {
Class base = target.getClass();
while (base != null) {
Object gsuper = base.getGenericSuperclass();
if (gsuper != null && gsuper instanceof ParameterizedType) {
Object o = ((ParameterizedType) gsuper).getActualTypeArguments()[0];
if (o instanceof Class) {
return (Class<?>) o;
}
}
base = base.getSuperclass();
}
return null;
}
I used this from my BaseRepository class like:
Class<?> type = type(SomeRepository);
where:
public class SomeRepository extends Repository<MyEntity> {
...
}