abstract class <T> - getClass type [duplicate] - java

I have a class like:
public abstract class BaseDao<T extends PersistentObject> {
protected Class<T> getClazz() {
return T.class;
}
// ...
}
But the compiler says to T.class;: Illegal class literal for the type parameter T.
How can I get the class of T?

It's definitely possible to extract it from Class#getGenericSuperclass() because it's not defined during runtime, but during compiletime by FooDao extends BaseDao<Foo>.
Here's a kickoff example how you could extract the desired generic super type in the constructor of the abstract class, taking a hierarchy of subclasses into account (along with a real world use case of applying it on generic EntityManager methods without the need to explicitly supply the type):
public abstract class BaseDao<E extends BaseEntity> {
#PersistenceContext
private EntityManager em;
private Class<E> type;
#SuppressWarnings("unchecked") // For the cast on Class<E>.
public BaseDao() {
Type type = getClass().getGenericSuperclass();
while (!(type instanceof ParameterizedType) || ((ParameterizedType) type).getRawType() != BaseDao.class) {
if (type instanceof ParameterizedType) {
type = ((Class<?>) ((ParameterizedType) type).getRawType()).getGenericSuperclass();
} else {
type = ((Class<?>) type).getGenericSuperclass();
}
}
this.type = (Class<E>) ((ParameterizedType) type).getActualTypeArguments()[0];
}
public E find(Long id) {
return em.find(type, id);
}
public List<E> list() {
return em.createQuery(String.format("SELECT e FROM %s e ORDER BY id", type.getSimpleName()), type).getResultList();
}
// ...
}

Actually, this is not as easy as it seems. There is a problem when you have rich type hierarchy and want to get generic parameter in the supertype. For example, you may have the following hierarchy:
public abstract class BaseDao<T extends BaseEntity> {
...
}
public abstract class SpecialDao<X extends SomeType, E extends BaseEntity> extends BaseDao<E> {
...
}
public class MyDao extends SpecialDao<TypeImpl, EntityImpl> {
...
}
Calling getClass().getGenericSuperclass() in an instance of MyDao returns SpecialDao<TypeImpl, EntityImpl>, but when you call it inside BaseDao method, you don't know how deep the generic hierarchy is. Moreover, as far as I know, you cannot obtain generic supertype of a supertype. Thus, when you invoke getClass().getGenericSuperclass().getRawType().getGenericSuperclass() (with some typecasting omitted for readability), you'll get BaseDao<E> (notice <E> instead of <T>). Since getRawType() strips all type-variable mapping from the type, we're starting with unmapped type variables X and E. Then getGenericSuperclass() just maps these type variables to their positions in BaseDao.
This behavior can be used so that we keep mapping from type variables to their actual values while traversing the type hierarchy. When we hit the class we want, we simply look up its type parameters in the map. Here is the code:
#SuppressWarnings("unchecked")
public static <T> Class<T> getGenericClassParameter(final Class<?> parameterizedSubClass, final Class<?> genericSuperClass, final int pos) {
// a mapping from type variables to actual values (classes)
Map<TypeVariable<?>, Class<?>> mapping = new HashMap<>();
Class<?> klass = parameterizedSubClass;
while (klass != null) {
Type type = klass.getGenericSuperclass();
if (type instanceof ParameterizedType) {
ParameterizedType parType = (ParameterizedType) type;
Type rawType = parType.getRawType();
if (rawType == genericSuperClass) {
// found
Type t = parType.getActualTypeArguments()[pos];
if (t instanceof Class<?>) {
return (Class<T>) t;
} else {
return (Class<T>) mapping.get((TypeVariable<?>)t);
}
}
// resolve
Type[] vars = ((GenericDeclaration)(parType.getRawType())).getTypeParameters();
Type[] args = parType.getActualTypeArguments();
for (int i = 0; i < vars.length; i++) {
if (args[i] instanceof Class<?>) {
mapping.put((TypeVariable)vars[i], (Class<?>)args[i]);
} else {
mapping.put((TypeVariable)vars[i], mapping.get((TypeVariable<?>)(args[i])));
}
}
klass = (Class<?>) rawType;
} else {
klass = klass.getSuperclass();
}
}
throw new IllegalArgumentException("no generic supertype for " + parameterizedSubClass + " of type " + genericSuperClass);
}

If Spring framework is available, you can do like here:
import org.springframework.core.GenericTypeResolver;
public abstract class BaseDao<T extends PersistentObject> {
protected Class<T> getClazz() {
return (Class<T>) GenericTypeResolver.resolveTypeArgument(getClass(), BaseDao.class);
}
}

If your class is abstract, you can try with this:
public class<T> getClassOfT() {
final ParameterizedType type = (ParameterizedType) this.getClass()
.getGenericSuperclass();
Class<T> clazz = (Class<T>) type.getActualTypeArguments()[0];
return clazz;
}
This only work if the instance is a direct subclass, and the type of the class you want is the first one (see the [0]).
If you have a large hierarchy of dao's, you can try fidn the BaseDao recursively and get the parametrized type
See a example here (see the output in the bottom)
Cheers and sorry for my bad english

Common way to sort this issue in a secure way is to add a constructor to store the class of the type.
Example in your context:
public abstract class BaseDao<T extends PersistentObject> {
private Class<T> classT;
BaseDao(Class<T> classT){
this.classT=classT;
}
protected Class<T> getClazz() {
return classT;
}
// ...
}

You might check out TypeTools (which I authored) for this:
Class<T> t = (Class<T>)TypeResolver.resolveRawArgument(BaseDao.class, getClass());

You can pass the type of class through the constructor of the abstract class, like this.
public abstract class BaseDao<T extends PersistentObject> {
private final Class<T> typeClass;
//Here in the constructor, you are asking for the actual Type Class.
BaseDao(Class<T> typeClass) {
this.typeClass = typeClass;
}
// ...
}
And in the concrete class pass the class type in the constructor.
public class BaseDaoImpl extends BaseDao<ActualType> {
BaseDaoImpl() {
//Here in the implementation, you pass the type class
super(ActualType.class);
}
}
The problem with this approach is that you cannot ensure that the type you are passing through the constructor is the actual type is being set in generic, so this can lead to issues if developers do not make sure they are passing the correct type through the constructor.

Related

How to pass a type parameter from the generic interface to a generic method? [duplicate]

I have a generics class, Foo<T>. In a method of Foo, I want to get the class instance of type T, but I just can't call T.class.
What is the preferred way to get around it using T.class?
The short answer is, that there is no way to find out the runtime type of generic type parameters in Java. I suggest reading the chapter about type erasure in the Java Tutorial for more details.
A popular solution to this is to pass the Class of the type parameter into the constructor of the generic type, e.g.
class Foo<T> {
final Class<T> typeParameterClass;
public Foo(Class<T> typeParameterClass) {
this.typeParameterClass = typeParameterClass;
}
public void bar() {
// you can access the typeParameterClass here and do whatever you like
}
}
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.
Pure Java solution
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]);
}
Spring solution
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 ";
}
Full code example
Some people are struggling in the comments to get this working so I wrote a small application to show both approaches in action.
https://github.com/benthurley82/generic-type-resolver-test
There is a small loophole however: if you define your Foo class as abstract.
That would mean you have to instantiate you class as:
Foo<MyType> myFoo = new Foo<MyType>(){};
(Note the double braces at the end.)
Now you can retrieve the type of T at runtime:
Type mySuperclass = myFoo.getClass().getGenericSuperclass();
Type tType = ((ParameterizedType)mySuperclass).getActualTypeArguments()[0];
Note however that mySuperclass has to be the superclass of the class definition actually defining the final type for T.
It is also not very elegant, but you have to decide whether you prefer new Foo<MyType>(){} or new Foo<MyType>(MyType.class); in your code.
For example:
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.NoSuchElementException;
/**
* Captures and silently ignores stack exceptions upon popping.
*/
public abstract class SilentStack<E> extends ArrayDeque<E> {
public E pop() {
try {
return super.pop();
}
catch( NoSuchElementException nsee ) {
return create();
}
}
public E create() {
try {
Type sooper = getClass().getGenericSuperclass();
Type t = ((ParameterizedType)sooper).getActualTypeArguments()[ 0 ];
return (E)(Class.forName( t.toString() ).newInstance());
}
catch( Exception e ) {
return null;
}
}
}
Then:
public class Main {
// Note the braces...
private Deque<String> stack = new SilentStack<String>(){};
public static void main( String args[] ) {
// Returns a new instance of String.
String s = stack.pop();
System.out.printf( "s = '%s'\n", s );
}
}
A standard approach/workaround/solution is to add a class object to the constructor(s), like:
public class Foo<T> {
private Class<T> type;
public Foo(Class<T> type) {
this.type = type;
}
public Class<T> getType() {
return type;
}
public T newInstance() {
return type.newInstance();
}
}
Here is a working solution:
#SuppressWarnings("unchecked")
private Class<T> getGenericTypeClass() {
    try {
        String className = ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0].getTypeName();
        Class<?> clazz = Class.forName(className);
        return (Class<T>) clazz;
    } catch (Exception e) {
        throw new IllegalStateException("Class is not parametrized with generic type!!! Please use extends <> ");
    }
}
NOTES:
Can be used only as superclass
Has to be extended with typed class (Child extends Generic<Integer>)
OR
Has to be created as anonymous implementation (new Generic<Integer>() {};)
Imagine you have an abstract superclass that is generic:
public abstract class Foo<? extends T> {}
And then you have a second class that extends Foo with a generic Bar that extends T:
public class Second extends Foo<Bar> {}
You can get the class Bar.class in the Foo class by selecting the Type (from bert bruynooghe answer) and infering it using Class instance:
Type mySuperclass = myFoo.getClass().getGenericSuperclass();
Type tType = ((ParameterizedType)mySuperclass).getActualTypeArguments()[0];
//Parse it as String
String className = tType.toString().split(" ")[1];
Class clazz = Class.forName(className);
You have to note this operation is not ideal, so it is a good idea to cache the computed value to avoid multiple calculations on this. One of the typical uses is in generic DAO implementation.
The final implementation:
public abstract class Foo<T> {
private Class<T> inferedClass;
public Class<T> getGenericClass(){
if(inferedClass == null){
Type mySuperclass = getClass().getGenericSuperclass();
Type tType = ((ParameterizedType)mySuperclass).getActualTypeArguments()[0];
String className = tType.toString().split(" ")[1];
inferedClass = Class.forName(className);
}
return inferedClass;
}
}
The value returned is Bar.class when invoked from Foo class in other function or from Bar class.
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, it is possible (without external libraries!)
The following is my (ugly, yet effective) solution for this problem:
import java.lang.reflect.TypeVariable;
public static <T> Class<T> getGenericClass() {
__<T> instance = new __<T>();
TypeVariable<?>[] parameters = instance.getClass().getTypeParameters();
return (Class<T>)parameters[0].getClass();
}
// Generic helper class which (only) provides type information. This avoids the
// usage of a local variable of type T, which would have to be initialized.
private final class __<T> {
private __() { }
}
You can't do it because of type erasure. See also Stack Overflow question Java generics - type erasure - when and what happens.
A better route than the Class the others suggested is to pass in an object that can do what you would have done with the Class, e.g., create a new instance.
interface Factory<T> {
T apply();
}
<T> void List<T> make10(Factory<T> factory) {
List<T> result = new ArrayList<T>();
for (int a = 0; a < 10; a++)
result.add(factory.apply());
return result;
}
class FooFactory<T> implements Factory<Foo<T>> {
public Foo<T> apply() {
return new Foo<T>();
}
}
List<Foo<Integer>> foos = make10(new FooFactory<Integer>());
I assume that, since you have a generic class, you would have a variable like that:
private T t;
(this variable needs to take a value at the constructor)
In that case you can simply create the following method:
Class<T> getClassOfInstance()
{
return (Class<T>) t.getClass();
}
Hope it helps!
It's possible:
class Foo<T> {
Class<T> clazz = (Class<T>) DAOUtil.getTypeArguments(Foo.class, this.getClass()).get(0);
}
You need two functions from hibernate-generic-dao/blob/master/dao/src/main/java/com/googlecode/genericdao/dao/DAOUtil.java.
For more explanations, see Reflecting generics.
I found a generic and simple way to do that. In my class I created a method that returns the generic type according to it's position in the class definition. Let's assume a class definition like this:
public class MyClass<A, B, C> {
}
Now let's create some attributes to persist the types:
public class MyClass<A, B, C> {
private Class<A> aType;
private Class<B> bType;
private Class<C> cType;
// Getters and setters (not necessary if you are going to use them internally)
}
Then you can create a generic method that returns the type based on the index of the generic definition:
/**
* Returns a {#link Type} object to identify generic types
* #return type
*/
private Type getGenericClassType(int index) {
// To make it use generics without supplying the class type
Type type = getClass().getGenericSuperclass();
while (!(type instanceof ParameterizedType)) {
if (type instanceof ParameterizedType) {
type = ((Class<?>) ((ParameterizedType) type).getRawType()).getGenericSuperclass();
} else {
type = ((Class<?>) type).getGenericSuperclass();
}
}
return ((ParameterizedType) type).getActualTypeArguments()[index];
}
Finally, in the constructor just call the method and send the index for each type. The complete code should look like:
public class MyClass<A, B, C> {
private Class<A> aType;
private Class<B> bType;
private Class<C> cType;
public MyClass() {
this.aType = (Class<A>) getGenericClassType(0);
this.bType = (Class<B>) getGenericClassType(1);
this.cType = (Class<C>) getGenericClassType(2);
}
/**
* Returns a {#link Type} object to identify generic types
* #return type
*/
private Type getGenericClassType(int index) {
Type type = getClass().getGenericSuperclass();
while (!(type instanceof ParameterizedType)) {
if (type instanceof ParameterizedType) {
type = ((Class<?>) ((ParameterizedType) type).getRawType()).getGenericSuperclass();
} else {
type = ((Class<?>) type).getGenericSuperclass();
}
}
return ((ParameterizedType) type).getActualTypeArguments()[index];
}
}
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() );
}
As explained in other answers, to use this ParameterizedType approach, you need to extend the class, but that seems like extra work to make a whole new class that extends it...
So, making the class abstract it forces you to extend it, thus satisfying the subclassing requirement. (using lombok's #Getter).
#Getter
public abstract class ConfigurationDefinition<T> {
private Class<T> type;
...
public ConfigurationDefinition(...) {
this.type = (Class<T>) ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments()[0];
...
}
}
Now to extend it without defining a new class. (Note the {} on the end... extended, but don't overwrite anything - unless you want to).
private ConfigurationDefinition<String> myConfigA = new ConfigurationDefinition<String>(...){};
private ConfigurationDefinition<File> myConfigB = new ConfigurationDefinition<File>(...){};
...
Class stringType = myConfigA.getType();
Class fileType = myConfigB.getType();
Many people don't know this trick! Actually, I just found it today! It works like a dream! Just check this example out:
public static void main(String[] args) {
Date d=new Date(); //Or anything you want!
printMethods(d);
}
public static <T> void printMethods(T t){
Class<T> clazz= (Class<T>) t.getClass(); // There you go!
for ( Method m : clazz.getMethods()){
System.out.println( m.getName() );
}
}
I've created an example based on one of two most promising solutions here from this question.
The result is however not so promising, at least for my use case.
Only one approach is working, but you need a super class containing the method and the generic has to be set in the child class and cannot be assigned dynamically (which my use case sadly is)
import org.junit.jupiter.api.Test;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
public class GenericTest {
/**
* only this will work!
*/
#Test
void testGetGenericTypeClassFromChildClassWithSpecifiedType() {
TestClassWithSpecifiedType parent = new TestClassWithSpecifiedType();
assertEquals(SomeGenericType.class, parent.getGenericTypeClass());
}
/**
* won't work!
*/
#Test
void testGetGenericTypeClassFromChildClassWithUnspecifiedType() {
TestClassWithUnspecifiedType<SomeGenericType> parent = new TestClassWithUnspecifiedType<>();
assertThrows(IllegalStateException.class, parent::getGenericTypeClass);
}
/**
* won't work
*/
#Test
void testGetGenericTypeClassWithUnspecifiedType() {
SomeGenericTypedClass<SomeGenericType> parent = new SomeGenericTypedClass<>();
assertThrows(IllegalStateException.class, parent::getGenericTypeClass);
}
/**
* won't work
* returns object instead!
*/
#Test
void testGetLoadedClassFromObject() {
Foo<SomeGenericType> foo = new Foo<>();
Class<?> barClass = foo.getBarClass();
assertEquals(SomeGenericType.class, barClass);
}
/**
* A class that has specified the type parameter
*/
public static class TestClassWithSpecifiedType extends AbstractGenericTypedClass<SomeGenericType> {
}
/**
* A class where the type parameter will be specified on demand
*
* #param <T>
*/
public static class TestClassWithUnspecifiedType<T> extends AbstractGenericTypedClass<T> {
}
/**
* An abstract class, because otherwise finding the parameter will not work
*/
#SuppressWarnings("unchecked")
public static abstract class AbstractGenericTypedClass<T> {
#SuppressWarnings("unchecked")
public Class<T> getGenericTypeClass() {
try {
String className = ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0].getTypeName();
Class<?> clazz = Class.forName(className);
return (Class<T>) clazz;
} catch (Exception e) {
throw new IllegalStateException("Class is not parametrized with generic type!!! Please use extends <> ");
}
}
}
/**
* A typed class without abstract super class
*
* #param <T>
*/
public static class SomeGenericTypedClass<T> {
#SuppressWarnings("unchecked")
public Class<T> getGenericTypeClass() {
try {
String className = ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0].getTypeName();
Class<?> clazz = Class.forName(className);
return (Class<T>) clazz;
} catch (Exception e) {
throw new IllegalStateException("Class is not parametrized with generic type!!! Please use extends <> ");
}
}
}
/**
* Some generic type - won't work with primitives such as String, Integer, Double!
*/
public static class SomeGenericType {
}
public static class Foo<T> {
// The class:
private final Class<?> barClass;
public Foo() {
try {
// Im giving it [0] cuz Bar is the first TypeParam
Type[] bounds = getClass().getTypeParameters()[0].getBounds();
// Here, we get the class now:
barClass = Class.forName(bounds[0].getTypeName());
} catch (ClassNotFoundException e) {
// will never happen!
throw new Error("Something impossible happened!", e);
}
}
public Class<?> getBarClass() {
return barClass;
}
}
}
I do not really understand why this has to be so complicated, but I bet there have to be some technical limitations for the dynamically setting of parameters.
public <T> T yourMethodSignature(Class<T> type) {
// get some object and check the type match the given type
Object result = ...
if (type.isAssignableFrom(result.getClass())) {
return (T)result;
} else {
// handle the error
}
}
If you are extending or implementing any class/interface that are using generics , you may get the Generic Type of parent class/interface, without modifying any existing class/interface at all.
There could be three possibilities,
Case 1
When your class is extending a class that is using Generics
public class TestGenerics {
public static void main(String[] args) {
Type type = TestMySuperGenericType.class.getGenericSuperclass();
Type[] gTypes = ((ParameterizedType)type).getActualTypeArguments();
for(Type gType : gTypes){
System.out.println("Generic type:"+gType.toString());
}
}
}
class GenericClass<T> {
public void print(T obj){};
}
class TestMySuperGenericType extends GenericClass<Integer> {
}
Case 2
When your class is implementing an interface that is using Generics
public class TestGenerics {
public static void main(String[] args) {
Type[] interfaces = TestMySuperGenericType.class.getGenericInterfaces();
for(Type type : interfaces){
Type[] gTypes = ((ParameterizedType)type).getActualTypeArguments();
for(Type gType : gTypes){
System.out.println("Generic type:"+gType.toString());
}
}
}
}
interface GenericClass<T> {
public void print(T obj);
}
class TestMySuperGenericType implements GenericClass<Integer> {
public void print(Integer obj){}
}
Case 3
When your interface is extending an interface that is using Generics
public class TestGenerics {
public static void main(String[] args) {
Type[] interfaces = TestMySuperGenericType.class.getGenericInterfaces();
for(Type type : interfaces){
Type[] gTypes = ((ParameterizedType)type).getActualTypeArguments();
for(Type gType : gTypes){
System.out.println("Generic type:"+gType.toString());
}
}
}
}
interface GenericClass<T> {
public void print(T obj);
}
interface TestMySuperGenericType extends GenericClass<Integer> {
}
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>
}
}
I wanted to pass T.class to a method which make use of Generics
The method readFile reads a .csv file specified by the fileName with fullpath. There can be csv files with different contents hence i need to pass the model file class so that i can get the appropriate objects. Since this is reading csv file i wanted to do in a generic way. For some reason or other none of the above solutions worked for me. I need to use
Class<? extends T> type to make it work. I use opencsv library for parsing the CSV files.
private <T>List<T> readFile(String fileName, Class<? extends T> type) {
List<T> dataList = new ArrayList<T>();
try {
File file = new File(fileName);
Reader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
Reader headerReader = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
CSVReader csvReader = new CSVReader(headerReader);
// create csv bean reader
CsvToBean<T> csvToBean = new CsvToBeanBuilder(reader)
.withType(type)
.withIgnoreLeadingWhiteSpace(true)
.build();
dataList = csvToBean.parse();
}
catch (Exception ex) {
logger.error("Error: ", ex);
}
return dataList;
}
This is how the readFile method is called
List<RigSurfaceCSV> rigSurfaceCSVDataList = readSurfaceFile(surfaceFileName, RigSurfaceCSV.class);
I'm using workaround for this:
class MyClass extends Foo<T> {
....
}
MyClass myClassInstance = MyClass.class.newInstance();

How to get instance of generic in interface

I have an interface with generic
public interface MessageCallback<T extends JsonModel> {
void onMessage(T t);
}
And I wanna get instance of T.
I found a solution where I can use reflection
public static <T> Class<T> getGenericClass(Class actualClass, int index) {
ParameterizedType genericSuperclass = (ParameterizedType) actualClass.getGenericSuperclass();
// Get generic class
return (Class<T>) genericSuperclass.getActualTypeArguments()[index];
}
But it throws exception.
java.lang.ClassCastException: java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType
I wanna know is there a solution without using reflection?
Extra. I also found this
class Foo<T> {
final Class<T> typeParameterClass;
public Foo(Class<T> typeParameterClass) {
this.typeParameterClass = typeParameterClass;
}
public void bar() {
// you can access the typeParameterClass here and do whatever you like
}
}
But its only for class. How I can solve my problem? Thanks for your answers.
And if you wanna know it isn't clean Java. It's in Android
About your first code, Class.getGenericSuperclass() returns the type representing the direct superclass of this class, that it Object in your case.
Class.getGenericInterfaces() that returns the Types representing the interfaces directly implemented by this class would be a better choice to retrieve the generic defined in the MessageCallback interface.
But it will probably not help you as the generic type will be which one statically declared in the MessageCallback interface : JsonModel and not which one defined in the subclass declaration that extends the interface.
About your second code, you should not worry about whether the parameter to capture the generic is Class or Type.
For example, the types declared in a generic class such as interface MessageCallback<T extends JsonModel> or a subclass of a generic class such as MessageCallbackImpl extends MessageCallback<MyJsonModel> are necessary classes as parameterized types can only be Classes. So storing the type of the generic type as Class is perfectly valid.
The Type class that is the common superinterface for all types in Java is much broader (raw types, parameterized types, array types, type variables and primitive types)
So to come back to your question : what you need is having a way to refer at runtime the generic type defined at compile and this idiom is a classical way to do that :
public Foo(Class<T> typeParameterClass) {
this.typeParameterClass = typeParameterClass;
}
You were on the right track.
Now suppose we have a generic interface, as in your example:
public interface MessageCallback<T extends JsonModel> {
void onMessage(T t);
}
And a concrete implementation of it:
class FooMessage {}
public class MyMessageCallback
implements MessageCallback<FooMessage extends JsonModel> {
#Override
public void onMessage(FooMessage t) {
System.out.println("Received foo");
}
}
You want to find the type passed into generic interface, MessageCallback, in this case FooMessage.
We can use reflection to find all interfaces that MyMessageCallback implements and for each interface, check if it is a generic interface then return all of its type parameters.
public static <T> Class<?>[] getGenericInterfaceParameter(Class clazz, Class<T> interfaceType) {
Class<?>[] result = new Class<?>[0];
// make sure interfaceType is a generic interface.
if(!interfaceType.isInterface() || interfaceType.getTypeParameters().length < 1) {
return result;
}
// get all interfaces implemented by concrete class.
Type[] interfaceTypes = clazz.getGenericInterfaces();
// for each interface the concrete class implements
// we check if that interface is actually equal to interfaceType
// and is a parametrized type,
// i.e has a type parameter.
// Once a match is found, we return the type parameters.
for(Type it : interfaceTypes) {
if(it instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType) it;
if(!parameterizedType.getRawType().equals(interfaceType)) {
continue;
}
Type[] typeParameters = parameterizedType.getActualTypeArguments();
result = new Class[typeParameters.length];
for(int j = 0; j < typeParameters.length; j++) {
result[j] = (Class) typeParameters[j];
}
}
}
return result;
}
Use the method to find type parameter of MyMessageCallback:
Class<?>[] params = getGenericInterfaceParameter(
MyCallback.class,
MessageCallback.class
);
System.out.println(params[0].getTypeName()); // MyMessageCallback

How to get (generic) type from class object

I would like to do this:
Get "Class" object from generic type T
but the other way round. So I would like to get the type of class objects. In Pseudocode I want to do something like this:
public class ExampleClass {
public static final Class<?>[] classes = new Class[]{MyClass1.class,
MyClass2.class, MyClass3.class, MyClass4.class, MyClass5.class};
public void myMethod() {
for (Class<?> c : DataBaseConfigUtils.classes ) {
MyObjectDAO<c.getType(), Integer> myObjectDAO = getMyObjectDAO(c);
ArrayList<c.getType()> list = myObjectDAO.queryAll();
for (c.getType() element : list) {
processElement(element);
}
}
}
public <T> MyObjectDAO<T, Integer> getMyObjectDAO(Class<T> c) {
return doSomething(c);
}
}
But there is nothing like Class.getType(). So how to get the type of a class object?
This is not possible in Java. The type is used only during the compilation and is erased. This information is not present in the bytecode or in the runtime environment.
https://docs.oracle.com/javase/tutorial/java/generics/erasure.html
Generics were introduced to the Java language to provide tighter type
checks at compile time and to support generic programming. To
implement generics, the Java compiler applies type erasure to:
Replace all type parameters in generic types with their bounds or Object if the type parameters are unbounded. The produced bytecode,
therefore, contains only ordinary classes, interfaces, and methods.
Insert type casts if necessary to preserve type safety.
Generate bridge methods to preserve polymorphism in extended generic types.
Type erasure ensures that no new classes are created for parameterized
types; consequently, generics incur no runtime overhead.
Your generic method getMyObjectDAO seems to answer your own question. If you have a variable with a wildcard in the type, you can use a generic helper method whenever you need to refer to the type in the code. You can refactor your code into this:
public class ExampleClass {
public static final Class<?>[] classes = new Class[]{MyClass1.class,
MyClass2.class, MyClass3.class, MyClass4.class, MyClass5.class};
public void myMethod() {
for (Class<?> c : DataBaseConfigUtils.classes ) {
act(c);
}
}
private <T> void act(Class<T> c) {
MyObjectDAO<T, Integer> myObjectDAO = getMyObjectDAO(c);
ArrayList<T> list = myObjectDAO.queryAll();
for (T element : list) {
processElement(element);
}
}
public <T> MyObjectDAO<T, Integer> getMyObjectDAO(Class<T> c) {
return doSomething(c);
}
}
It is important to be aware of the limitations of this. Suppose you have a variable of type List<?>. While it is possible to use a private generic helper method that will enable you to treat it as a List<T> and use the type T in code, type erasure means that you can't query the type T at runtime. So all of the following are illegal
if (T == String) { //do something; }
if (T.class == String.class) { //do something }
if (a instanceof T) { //do something }
The usual workaround for this is to make one of the arguments to the helper method a Class<T> object, because you can do
if (clazz == String.class) { //do something }
(Note that this will not work if T is itself a generic type, because you cannot write List<String>.class, for example. There is a workaround called super type tokens for this.)
Since the objects you are using are Class objects, type erasure should not cause you any problems at all.
For example:
ParameterizedType superclass = (ParameterizedType)getClass().getGenericSuperclass();
this.entityClass = (Class<T>) superclass.getActualTypeArguments()[0];
But if you want to add as type Generic I suppose you have design errors. Best Practice for it -
You should create Parent (abstract) class or Interface and use it in your code:
public abstract class ABaseEntity{
...
}
public class Child extends ABaseEntity{
...
}
Create base dao with your BaseEntity whiche will be return some entities extended you ABaseEntity :
public class AbstarctDAO<T extends ABaseEntity, PK extends Serializable> {
#PersistenceContext
protected EntityManager em;
protected Class<T> entityClass;
protected AbstarctDAO() {
}
#PostConstruct
public void init(){
final ParameterizedType superclass = (ParameterizedType)getClass().getGenericSuperclass();
this.entityClass = (Class<T>) superclass.getActualTypeArguments()[0];
}
#Override
public T create(T object) throws Exception {
em.persist(object);
em.flush();
return object;
}
...
}
Excecution example:
1.
AbstarctDAO dao = new AbstarctDAO();
try {
dao.create(new Child ());
}catch (Exception e){
}
2.
# Stateless
# Transactional
public class ChildDAO extends AbstarctDAO<Child , Long> {
#Transactional(Transactional.TxType.SUPPORTS)
public Child getChildByName(String name) {
...
return (Child)query.getSingleResult();
}
}

How do I get a class instance of generic type T?

I have a generics class, Foo<T>. In a method of Foo, I want to get the class instance of type T, but I just can't call T.class.
What is the preferred way to get around it using T.class?
The short answer is, that there is no way to find out the runtime type of generic type parameters in Java. I suggest reading the chapter about type erasure in the Java Tutorial for more details.
A popular solution to this is to pass the Class of the type parameter into the constructor of the generic type, e.g.
class Foo<T> {
final Class<T> typeParameterClass;
public Foo(Class<T> typeParameterClass) {
this.typeParameterClass = typeParameterClass;
}
public void bar() {
// you can access the typeParameterClass here and do whatever you like
}
}
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.
Pure Java solution
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]);
}
Spring solution
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 ";
}
Full code example
Some people are struggling in the comments to get this working so I wrote a small application to show both approaches in action.
https://github.com/benthurley82/generic-type-resolver-test
There is a small loophole however: if you define your Foo class as abstract.
That would mean you have to instantiate you class as:
Foo<MyType> myFoo = new Foo<MyType>(){};
(Note the double braces at the end.)
Now you can retrieve the type of T at runtime:
Type mySuperclass = myFoo.getClass().getGenericSuperclass();
Type tType = ((ParameterizedType)mySuperclass).getActualTypeArguments()[0];
Note however that mySuperclass has to be the superclass of the class definition actually defining the final type for T.
It is also not very elegant, but you have to decide whether you prefer new Foo<MyType>(){} or new Foo<MyType>(MyType.class); in your code.
For example:
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.NoSuchElementException;
/**
* Captures and silently ignores stack exceptions upon popping.
*/
public abstract class SilentStack<E> extends ArrayDeque<E> {
public E pop() {
try {
return super.pop();
}
catch( NoSuchElementException nsee ) {
return create();
}
}
public E create() {
try {
Type sooper = getClass().getGenericSuperclass();
Type t = ((ParameterizedType)sooper).getActualTypeArguments()[ 0 ];
return (E)(Class.forName( t.toString() ).newInstance());
}
catch( Exception e ) {
return null;
}
}
}
Then:
public class Main {
// Note the braces...
private Deque<String> stack = new SilentStack<String>(){};
public static void main( String args[] ) {
// Returns a new instance of String.
String s = stack.pop();
System.out.printf( "s = '%s'\n", s );
}
}
A standard approach/workaround/solution is to add a class object to the constructor(s), like:
public class Foo<T> {
private Class<T> type;
public Foo(Class<T> type) {
this.type = type;
}
public Class<T> getType() {
return type;
}
public T newInstance() {
return type.newInstance();
}
}
Imagine you have an abstract superclass that is generic:
public abstract class Foo<? extends T> {}
And then you have a second class that extends Foo with a generic Bar that extends T:
public class Second extends Foo<Bar> {}
You can get the class Bar.class in the Foo class by selecting the Type (from bert bruynooghe answer) and infering it using Class instance:
Type mySuperclass = myFoo.getClass().getGenericSuperclass();
Type tType = ((ParameterizedType)mySuperclass).getActualTypeArguments()[0];
//Parse it as String
String className = tType.toString().split(" ")[1];
Class clazz = Class.forName(className);
You have to note this operation is not ideal, so it is a good idea to cache the computed value to avoid multiple calculations on this. One of the typical uses is in generic DAO implementation.
The final implementation:
public abstract class Foo<T> {
private Class<T> inferedClass;
public Class<T> getGenericClass(){
if(inferedClass == null){
Type mySuperclass = getClass().getGenericSuperclass();
Type tType = ((ParameterizedType)mySuperclass).getActualTypeArguments()[0];
String className = tType.toString().split(" ")[1];
inferedClass = Class.forName(className);
}
return inferedClass;
}
}
The value returned is Bar.class when invoked from Foo class in other function or from Bar class.
Here is a working solution:
#SuppressWarnings("unchecked")
private Class<T> getGenericTypeClass() {
    try {
        String className = ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0].getTypeName();
        Class<?> clazz = Class.forName(className);
        return (Class<T>) clazz;
    } catch (Exception e) {
        throw new IllegalStateException("Class is not parametrized with generic type!!! Please use extends <> ");
    }
}
NOTES:
Can be used only as superclass
Has to be extended with typed class (Child extends Generic<Integer>)
OR
Has to be created as anonymous implementation (new Generic<Integer>() {};)
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, it is possible (without external libraries!)
The following is my (ugly, yet effective) solution for this problem:
import java.lang.reflect.TypeVariable;
public static <T> Class<T> getGenericClass() {
__<T> instance = new __<T>();
TypeVariable<?>[] parameters = instance.getClass().getTypeParameters();
return (Class<T>)parameters[0].getClass();
}
// Generic helper class which (only) provides type information. This avoids the
// usage of a local variable of type T, which would have to be initialized.
private final class __<T> {
private __() { }
}
You can't do it because of type erasure. See also Stack Overflow question Java generics - type erasure - when and what happens.
A better route than the Class the others suggested is to pass in an object that can do what you would have done with the Class, e.g., create a new instance.
interface Factory<T> {
T apply();
}
<T> void List<T> make10(Factory<T> factory) {
List<T> result = new ArrayList<T>();
for (int a = 0; a < 10; a++)
result.add(factory.apply());
return result;
}
class FooFactory<T> implements Factory<Foo<T>> {
public Foo<T> apply() {
return new Foo<T>();
}
}
List<Foo<Integer>> foos = make10(new FooFactory<Integer>());
I assume that, since you have a generic class, you would have a variable like that:
private T t;
(this variable needs to take a value at the constructor)
In that case you can simply create the following method:
Class<T> getClassOfInstance()
{
return (Class<T>) t.getClass();
}
Hope it helps!
It's possible:
class Foo<T> {
Class<T> clazz = (Class<T>) DAOUtil.getTypeArguments(Foo.class, this.getClass()).get(0);
}
You need two functions from hibernate-generic-dao/blob/master/dao/src/main/java/com/googlecode/genericdao/dao/DAOUtil.java.
For more explanations, see Reflecting generics.
I found a generic and simple way to do that. In my class I created a method that returns the generic type according to it's position in the class definition. Let's assume a class definition like this:
public class MyClass<A, B, C> {
}
Now let's create some attributes to persist the types:
public class MyClass<A, B, C> {
private Class<A> aType;
private Class<B> bType;
private Class<C> cType;
// Getters and setters (not necessary if you are going to use them internally)
}
Then you can create a generic method that returns the type based on the index of the generic definition:
/**
* Returns a {#link Type} object to identify generic types
* #return type
*/
private Type getGenericClassType(int index) {
// To make it use generics without supplying the class type
Type type = getClass().getGenericSuperclass();
while (!(type instanceof ParameterizedType)) {
if (type instanceof ParameterizedType) {
type = ((Class<?>) ((ParameterizedType) type).getRawType()).getGenericSuperclass();
} else {
type = ((Class<?>) type).getGenericSuperclass();
}
}
return ((ParameterizedType) type).getActualTypeArguments()[index];
}
Finally, in the constructor just call the method and send the index for each type. The complete code should look like:
public class MyClass<A, B, C> {
private Class<A> aType;
private Class<B> bType;
private Class<C> cType;
public MyClass() {
this.aType = (Class<A>) getGenericClassType(0);
this.bType = (Class<B>) getGenericClassType(1);
this.cType = (Class<C>) getGenericClassType(2);
}
/**
* Returns a {#link Type} object to identify generic types
* #return type
*/
private Type getGenericClassType(int index) {
Type type = getClass().getGenericSuperclass();
while (!(type instanceof ParameterizedType)) {
if (type instanceof ParameterizedType) {
type = ((Class<?>) ((ParameterizedType) type).getRawType()).getGenericSuperclass();
} else {
type = ((Class<?>) type).getGenericSuperclass();
}
}
return ((ParameterizedType) type).getActualTypeArguments()[index];
}
}
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() );
}
As explained in other answers, to use this ParameterizedType approach, you need to extend the class, but that seems like extra work to make a whole new class that extends it...
So, making the class abstract it forces you to extend it, thus satisfying the subclassing requirement. (using lombok's #Getter).
#Getter
public abstract class ConfigurationDefinition<T> {
private Class<T> type;
...
public ConfigurationDefinition(...) {
this.type = (Class<T>) ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments()[0];
...
}
}
Now to extend it without defining a new class. (Note the {} on the end... extended, but don't overwrite anything - unless you want to).
private ConfigurationDefinition<String> myConfigA = new ConfigurationDefinition<String>(...){};
private ConfigurationDefinition<File> myConfigB = new ConfigurationDefinition<File>(...){};
...
Class stringType = myConfigA.getType();
Class fileType = myConfigB.getType();
Many people don't know this trick! Actually, I just found it today! It works like a dream! Just check this example out:
public static void main(String[] args) {
Date d=new Date(); //Or anything you want!
printMethods(d);
}
public static <T> void printMethods(T t){
Class<T> clazz= (Class<T>) t.getClass(); // There you go!
for ( Method m : clazz.getMethods()){
System.out.println( m.getName() );
}
}
I've created an example based on one of two most promising solutions here from this question.
The result is however not so promising, at least for my use case.
Only one approach is working, but you need a super class containing the method and the generic has to be set in the child class and cannot be assigned dynamically (which my use case sadly is)
import org.junit.jupiter.api.Test;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
public class GenericTest {
/**
* only this will work!
*/
#Test
void testGetGenericTypeClassFromChildClassWithSpecifiedType() {
TestClassWithSpecifiedType parent = new TestClassWithSpecifiedType();
assertEquals(SomeGenericType.class, parent.getGenericTypeClass());
}
/**
* won't work!
*/
#Test
void testGetGenericTypeClassFromChildClassWithUnspecifiedType() {
TestClassWithUnspecifiedType<SomeGenericType> parent = new TestClassWithUnspecifiedType<>();
assertThrows(IllegalStateException.class, parent::getGenericTypeClass);
}
/**
* won't work
*/
#Test
void testGetGenericTypeClassWithUnspecifiedType() {
SomeGenericTypedClass<SomeGenericType> parent = new SomeGenericTypedClass<>();
assertThrows(IllegalStateException.class, parent::getGenericTypeClass);
}
/**
* won't work
* returns object instead!
*/
#Test
void testGetLoadedClassFromObject() {
Foo<SomeGenericType> foo = new Foo<>();
Class<?> barClass = foo.getBarClass();
assertEquals(SomeGenericType.class, barClass);
}
/**
* A class that has specified the type parameter
*/
public static class TestClassWithSpecifiedType extends AbstractGenericTypedClass<SomeGenericType> {
}
/**
* A class where the type parameter will be specified on demand
*
* #param <T>
*/
public static class TestClassWithUnspecifiedType<T> extends AbstractGenericTypedClass<T> {
}
/**
* An abstract class, because otherwise finding the parameter will not work
*/
#SuppressWarnings("unchecked")
public static abstract class AbstractGenericTypedClass<T> {
#SuppressWarnings("unchecked")
public Class<T> getGenericTypeClass() {
try {
String className = ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0].getTypeName();
Class<?> clazz = Class.forName(className);
return (Class<T>) clazz;
} catch (Exception e) {
throw new IllegalStateException("Class is not parametrized with generic type!!! Please use extends <> ");
}
}
}
/**
* A typed class without abstract super class
*
* #param <T>
*/
public static class SomeGenericTypedClass<T> {
#SuppressWarnings("unchecked")
public Class<T> getGenericTypeClass() {
try {
String className = ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0].getTypeName();
Class<?> clazz = Class.forName(className);
return (Class<T>) clazz;
} catch (Exception e) {
throw new IllegalStateException("Class is not parametrized with generic type!!! Please use extends <> ");
}
}
}
/**
* Some generic type - won't work with primitives such as String, Integer, Double!
*/
public static class SomeGenericType {
}
public static class Foo<T> {
// The class:
private final Class<?> barClass;
public Foo() {
try {
// Im giving it [0] cuz Bar is the first TypeParam
Type[] bounds = getClass().getTypeParameters()[0].getBounds();
// Here, we get the class now:
barClass = Class.forName(bounds[0].getTypeName());
} catch (ClassNotFoundException e) {
// will never happen!
throw new Error("Something impossible happened!", e);
}
}
public Class<?> getBarClass() {
return barClass;
}
}
}
I do not really understand why this has to be so complicated, but I bet there have to be some technical limitations for the dynamically setting of parameters.
public <T> T yourMethodSignature(Class<T> type) {
// get some object and check the type match the given type
Object result = ...
if (type.isAssignableFrom(result.getClass())) {
return (T)result;
} else {
// handle the error
}
}
If you are extending or implementing any class/interface that are using generics , you may get the Generic Type of parent class/interface, without modifying any existing class/interface at all.
There could be three possibilities,
Case 1
When your class is extending a class that is using Generics
public class TestGenerics {
public static void main(String[] args) {
Type type = TestMySuperGenericType.class.getGenericSuperclass();
Type[] gTypes = ((ParameterizedType)type).getActualTypeArguments();
for(Type gType : gTypes){
System.out.println("Generic type:"+gType.toString());
}
}
}
class GenericClass<T> {
public void print(T obj){};
}
class TestMySuperGenericType extends GenericClass<Integer> {
}
Case 2
When your class is implementing an interface that is using Generics
public class TestGenerics {
public static void main(String[] args) {
Type[] interfaces = TestMySuperGenericType.class.getGenericInterfaces();
for(Type type : interfaces){
Type[] gTypes = ((ParameterizedType)type).getActualTypeArguments();
for(Type gType : gTypes){
System.out.println("Generic type:"+gType.toString());
}
}
}
}
interface GenericClass<T> {
public void print(T obj);
}
class TestMySuperGenericType implements GenericClass<Integer> {
public void print(Integer obj){}
}
Case 3
When your interface is extending an interface that is using Generics
public class TestGenerics {
public static void main(String[] args) {
Type[] interfaces = TestMySuperGenericType.class.getGenericInterfaces();
for(Type type : interfaces){
Type[] gTypes = ((ParameterizedType)type).getActualTypeArguments();
for(Type gType : gTypes){
System.out.println("Generic type:"+gType.toString());
}
}
}
}
interface GenericClass<T> {
public void print(T obj);
}
interface TestMySuperGenericType extends GenericClass<Integer> {
}
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>
}
}
I wanted to pass T.class to a method which make use of Generics
The method readFile reads a .csv file specified by the fileName with fullpath. There can be csv files with different contents hence i need to pass the model file class so that i can get the appropriate objects. Since this is reading csv file i wanted to do in a generic way. For some reason or other none of the above solutions worked for me. I need to use
Class<? extends T> type to make it work. I use opencsv library for parsing the CSV files.
private <T>List<T> readFile(String fileName, Class<? extends T> type) {
List<T> dataList = new ArrayList<T>();
try {
File file = new File(fileName);
Reader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
Reader headerReader = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
CSVReader csvReader = new CSVReader(headerReader);
// create csv bean reader
CsvToBean<T> csvToBean = new CsvToBeanBuilder(reader)
.withType(type)
.withIgnoreLeadingWhiteSpace(true)
.build();
dataList = csvToBean.parse();
}
catch (Exception ex) {
logger.error("Error: ", ex);
}
return dataList;
}
This is how the readFile method is called
List<RigSurfaceCSV> rigSurfaceCSVDataList = readSurfaceFile(surfaceFileName, RigSurfaceCSV.class);
I'm using workaround for this:
class MyClass extends Foo<T> {
....
}
MyClass myClassInstance = MyClass.class.newInstance();

How to determine the class of a generic type?

I'm creating a generic class and in one of the methods I need to know the Class of the generic type currently in use. The reason is that one of the method's I call expects this as an argument.
Example:
public class MyGenericClass<T> {
public void doSomething() {
// Snip...
// Call to a 3rd party lib
T bean = (T)someObject.create(T.class);
// Snip...
}
}
Clearly the example above doesn't work and results in the following error: Illegal class literal for the type parameter T.
My question is: does someone know a good alternative or workaround for this?
Still the same problems : Generic informations are erased at runtime, it cannot be recovered. A workaround is to pass the class T in parameter of a static method :
public class MyGenericClass<T> {
private final Class<T> clazz;
public static <U> MyGenericClass<U> createMyGeneric(Class<U> clazz) {
return new MyGenericClass<U>(clazz);
}
protected MyGenericClass(Class<T> clazz) {
this.clazz = clazz;
}
public void doSomething() {
T instance = clazz.newInstance();
}
}
It's ugly, but it works.
I was just pointed to this solution:
import java.lang.reflect.ParameterizedType;
public abstract class A<B> {
public Class<B> g() throws Exception {
ParameterizedType superclass =
(ParameterizedType) getClass().getGenericSuperclass();
return (Class<B>) superclass.getActualTypeArguments()[0];
}
}
This works if A is given a concrete type by a subclass:
new A<String>() {}.g() // this will work
class B extends A<String> {}
new B().g() // this will work
class C<T> extends A<T> {}
new C<String>().g() // this will NOT work
Unfortunately Christoph's solution as written only works in very limited circumstances. [EDIT: as commented below I no longer remember my reasoning for this sentence and it is likely wrong: "Note that this will only work in abstract classes, first of all."] The next difficulty is that g() only works from DIRECT subclasses of A. We can fix that, though:
private Class<?> extractClassFromType(Type t) throws ClassCastException {
if (t instanceof Class<?>) {
return (Class<?>)t;
}
return (Class<?>)((ParameterizedType)t).getRawType();
}
public Class<B> g() throws ClassCastException {
Class<?> superClass = getClass(); // initial value
Type superType;
do {
superType = superClass.getGenericSuperclass();
superClass = extractClassFromType(superType);
} while (! (superClass.equals(A.class)));
Type actualArg = ((ParameterizedType)superType).getActualTypeArguments()[0];
return (Class<B>)extractClassFromType(actualArg);
}
This will work in many situations in practice, but not ALL the time. Consider:
public class Foo<U,T extends Collection<?>> extends A<T> {}
(new Foo<String,List<Object>>() {}).g();
This will throw a ClassCastException, because the type argument here isn't a Class or a ParameterizedType at all; it's the TypeVariable T. So now you would be stuck trying to figure out what type T was supposed to stand for, and so on down the rabbit hole.
I think the only reasonable, general answer is something akin to Nicolas's initial answer -- in general, if your class needs to instantiate objects of some other class that is unknown at compile-time, users of your class need to pass that class literal (or, perhaps, a Factory) to your class explicitly and not rely solely on generics.
i find another way to obtain the Class of the generic object
public Class<?> getGenericClass(){
Class<?> result =null;
Type type =this.getClass().getGenericSuperclass();
if(type instanceofParameterizedType){
ParameterizedType pt =(ParameterizedType) type;
Type[] fieldArgTypes = pt.getActualTypeArguments();
result =(Class<?>) fieldArgTypes[0];
}
return result;
}
I will elaborate on Christoph's solution.
Here is the ClassGetter abstract class:
private abstract class ClassGetter<T> {
public final Class<T> get() {
final ParameterizedType superclass = (ParameterizedType)
getClass().getGenericSuperclass();
return (Class<T>)superclass.getActualTypeArguments()[0];
}
}
Here is a static method which uses the above class to find a generic class' type:
public static <T> Class<T> getGenericClass() {
return new ClassGetter<T>() {}.get();
}
As an example of it's usage, you could make this method:
public static final <T> T instantiate() {
final Class<T> clazz = getGenericClass();
try {
return clazz.getConstructor((Class[])null).newInstance(null);
} catch (Exception e) {
return null;
}
}
And then use it like this:
T var = instantiate();
public class DatabaseAccessUtil {
EntityManagerFactory entitymanagerfactory;
EntityManager entitymanager;
public DatabaseAccessUtil() {
entitymanagerfactory=Persistence.createEntityManagerFactory("bookmyshow");
entitymanager=entitymanagerfactory.createEntityManager();
}
public void save (T t) {
entitymanager.getTransaction().begin();
entitymanager.persist(t);
entitymanager.getTransaction().commit();
}
public void update(T t) {
entitymanager.getTransaction().begin();
entitymanager.persist(t);
entitymanager.getTransaction().commit();
}
public void delete(T t) {
entitymanager.getTransaction().begin();
entitymanager.remove(t);
entitymanager.getTransaction().commit();
}
public Object retrieve(Query query) {
return query.getSingleResult();
}
//call the method - retrieve(object,requiredclass.class)
public Object retrieve(Object primaryKey,class clazz) throws Exception {
return entitymanager.find(clazz,primaryKey);
}
}

Categories

Resources