I have a generics class, Foo
. In a method of Foo
, I want to get the class instance of type T
, but I just can\'t call T.
I'm using workaround for this:
class MyClass extends Foo<T> {
....
}
MyClass myClassInstance = MyClass.class.newInstance();
I had this problem in an abstract generic class. In this particular case, the solution is simpler:
abstract class Foo<T> {
abstract Class<T> getTClass();
//...
}
and later on the derived class:
class Bar extends Foo<Whatever> {
@Override
Class<T> getTClass() {
return Whatever.class;
}
}
Actually, I suppose you have a field in your class of type T. If there's no field of type T, what's the point of having a generic Type? So, you can simply do an instanceof on that field.
In my case, I have a
List<T> items;in my class, and I check if the class type is "Locality" by
if (items.get(0) instanceof Locality) ...
Of course, this only works if the total number of possible classes is limited.
This question is old, but now the best is use google Gson
.
An example to get custom viewModel
.
Class<CustomViewModel<String>> clazz = new GenericClass<CustomViewModel<String>>().getRawType();
CustomViewModel<String> viewModel = viewModelProvider.get(clazz);
Generic type class
class GenericClass<T>(private val rawType: Class<*>) {
constructor():this(`$Gson$Types`.getRawType(object : TypeToken<T>() {}.getType()))
fun getRawType(): Class<T> {
return rawType as Class<T>
}
}
That is pretty straight forward. If you need from within the same class:
Class clazz = this.getClass();
ParameterizedType parameterizedType = (ParameterizedType) clazz.getGenericSuperclass();
try {
Class typeClass = Class.forName( parameterizedType.getActualTypeArguments()[0].getTypeName() );
// You have the instance of type 'T' in typeClass variable
System.out.println( "Class instance name: "+ typeClass.getName() );
} catch (ClassNotFoundException e) {
System.out.println( "ClassNotFound!! Something wrong! "+ e.getMessage() );
}
I was looking for a way to do this myself without adding an extra dependency to the classpath. After some investigation I found that it is possible as long as you have a generic supertype. This was OK for me as I was working with a DAO layer with a generic layer supertype. If this fits your scenario then it's the neatest approach IMHO.
Most generics use cases I've come across have some kind of generic supertype e.g. List<T>
for ArrayList<T>
or GenericDAO<T>
for DAO<T>
, etc.
The article Accessing generic types at runtime in Java explains how you can do it using pure Java.
@SuppressWarnings("unchecked")
public GenericJpaDao() {
this.entityBeanType = ((Class) ((ParameterizedType) getClass()
.getGenericSuperclass()).getActualTypeArguments()[0]);
}
My project was using Spring which is even better as Spring has a handy utility method for finding the type. This is the best approach for me as it looks neatest. I guess if you weren't using Spring you could write your own utility method.
import org.springframework.core.GenericTypeResolver;
public abstract class AbstractHibernateDao<T extends DomainObject> implements DataAccessObject<T>
{
@Autowired
private SessionFactory sessionFactory;
private final Class<T> genericType;
private final String RECORD_COUNT_HQL;
private final String FIND_ALL_HQL;
@SuppressWarnings("unchecked")
public AbstractHibernateDao()
{
this.genericType = (Class<T>) GenericTypeResolver.resolveTypeArgument(getClass(), AbstractHibernateDao.class);
this.RECORD_COUNT_HQL = "select count(*) from " + this.genericType.getName();
this.FIND_ALL_HQL = "from " + this.genericType.getName() + " t ";
}