919

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?

Michael
44.4k12 gold badges97 silver badges143 bronze badges
asked Aug 9, 2010 at 6:58
6
  • 2
    Try answers in this question.I think its similar. stackoverflow.com/questions/1942644/… Commented Aug 9, 2010 at 7:37
  • 3
    possible duplicate of Get generic type of class at runtime Commented Apr 1, 2014 at 14:06
  • 1
    possible duplicate of Instantiating a generic class in Java Commented Oct 14, 2014 at 17:12
  • 2
    import com.fasterxml.jackson.core.type.TypeReference; new TypeReference<T>(){} Commented Feb 6, 2019 at 11:59
  • Yup, as the comment above suggests, workarounded it by providing new TypeReference<Foo<Bar>>() {} as a parameter to my deserialized model reader method. Commented Dec 27, 2021 at 21:17

25 Answers 25

705

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
 }
}
answered Aug 9, 2010 at 7:03

6 Comments

This answer does provide a valid solution but it is inaccurate to say there is no way to find the generic type at runtime. It turns out type erasure is far more complex than a blanket erasure. My answer shows you how to get the classes generic type.
@BenThurley Neat trick, but as far as I can see it only works if there is a generic supertype for it to use. In my example, you can't retrieve the type of T in Foo<T>.
@webjockey No, you shouldn't. Assigning the typeParameterClass without a default assignment in the constructor is perfectly fine. There's no need to set it a second time.
This is the first solution that comes to mind, but at times it is not you who will be creating/initiating objects. So you will not be able to use constructor. For e.g. while retrieving JPA entities from database.
@ZsoltTörök I think I found the solution to this problem. Please check my answer: stackoverflow.com/a/64504193/9432967
|
320

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 with a non-generic subclass. 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 Class reflectClassType() {
 return ((Class) ((ParameterizedType) getClass()
 .getGenericSuperclass()).getActualTypeArguments()[0]);
}

There are several limitations with this code. It will not work in all cases involving several levels of abstraction, or when your type is an array (e.g. int[]). For a more complete solution that extends this for more cases, see this article.

Note again that this method only works with a non-generic/raw subclass. If you try to do this with a generic class, the type arguments will be unresolved, generic TypeVariableImpl objects still, whose class is null. For example:

class Generic<T>{
 @SuppressWarnings("unchecked")
 public Class reflectClassType() {
 return ((Class) ((ParameterizedType) getClass()
 .getGenericSuperclass()).getActualTypeArguments()[0]);
 }
}
class ChildGeneric<T> extends Generic<T>{}
class ChildString extends Generic<String>{}
// Error! Won't work, since the subclass is generic
new ChildGeneric<String>().reflectClassType();
// Works; we create an anonymous, trivial, non-generic subclass
new ChildGeneric<String>(){}.reflectClsasType();
// Works; we create an explicit non-generic subclass
new ChildString().reflectClassType(); // okay

Spring solution

Spring provides a utility class GenericTypeResolver, which implements a more robust version of this technique. It comes with its own subtle limitations. In general, it will only work if the called for a non-generic class.

My project was using Spring so 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

Note that in this code, the non-generic Foo subclass has a generic superclass AbstractFoo:

public class Foo extends AbstractFoo<GenericType>

which is what allows this method to work.

Azmisov
7,3598 gold badges58 silver badges79 bronze badges
answered Feb 8, 2012 at 22:14

15 Comments

please clarify meaning of resolveTypeArgument arguments
getClass() is a method of java.lang.Object which will return the class of the specific object at runtime, this is the object you want to resolve the type for. AbstractHibernateDao.class is just the name of the base class or superclass of the generic type class hierarchy. The import statement is included so you should be able to easily find the docs and check yourself. This is the page docs.spring.io/spring/docs/current/javadoc-api/org/…
The link in "Pure Java solution" is broken, it is now blog.xebia.com/acessing-generic-types-at-runtime-in-java
java.lang.ClassCastException: java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType
@BenThurley I just went down the rabbit hole to understand why your code didn't work form me. The answer is that unfortunately it doesn't really work at all: your code gets the type parameter from the declaration of the class, not the type with which the generic class happened to be instantiated. In your github example Foo extends AbstractFoo<GenericType> where GenericType is a fixed class you also defined, so in this case the generic type argument of Foo can be read from the declaration. But if GenericType was instead a type parameter, this would not work.
|
121

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 );
 }
}
answered Apr 16, 2011 at 5:51

4 Comments

This is easily the best answer on here! Also, for what it's worth, this is the strategy that Google Guice uses for binding classes with TypeLiteral
Note that every time this method of object construction is used, a new anonymous class is created. In other words, two objects a and b created this way will both extend the same class but not have identical instance classes. a.getClass() != b.getClass()
There is one scenario in which this doesn't work. If Foo should implement an interface, such as Serializable, than the anonymous class would not be Serializable unless the class instantiating is. I tried to workaround it by creating a serializable factory class that creates the anonymous class derived from Foo, but then, for some reason, getActualTypeArguments returns the generic type instead of the actual class. For example: (new FooFactory<MyType>()).createFoo()
In your example the Class.forName( t.toString() ) raised a ClassNotFoundException for me. Use this instead to get the real class name: Class.forName( t.getTypeName() )
45

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();
 }
 }
Paul Whelan
16.8k12 gold badges54 silver badges86 bronze badges
answered Aug 9, 2010 at 7:07

3 Comments

But it seemed cannot @autowired in actual use, any way to work around?
@AlfredHuang The work around would be to create a bean for the class that does this and not rely on autowiring.
@Calebj Okay, How would I be doing that?
24

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

  1. Has to be extended with typed class (Child extends Generic<Integer>)

OR

  1. Has to be created as anonymous implementation (new Generic<Integer>() {};)
Lino
20k6 gold badges54 silver badges72 bronze badges
answered Nov 30, 2015 at 11:09

1 Comment

getTypeName calls toString, so can be replaced by .getActualTypeArguments()[0].toString();
23

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.

answered Mar 26, 2014 at 23:20

1 Comment

toString().split(" ")[1] that was the problem, avoid the "class "
14

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;
 }
}
Octavia Togami
4,3564 gold badges33 silver badges50 bronze badges
answered Oct 21, 2012 at 2:41

1 Comment

Yes it is, but i would like to leave very minimum that needs to be done while extending this class. Check droidpl's answer
13

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 __() { }
}
answered Nov 7, 2017 at 6:20

3 Comments

I know this is a few years old, but this is returning me a TypeVariableImpl<T> rather than the class type of T itself
Be that as it may, TypeVariableImpl<T> seems to be assignable to Class<T>, doesn't it? At least, I do not get any compiler errors.... I have to admit, that I'm not a java guy though ... so I might be missing some obvious flaw/drawback/consequence.
I'm trying to use it in the creation of an EnumSet, and it doesn't seem to like it
12

You can't do it because of type erasure. See also Stack Overflow question Java generics - type erasure - when and what happens .

answered Aug 9, 2010 at 7:02

Comments

10

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>());
answered Aug 9, 2010 at 11:47

2 Comments

@ Ricky Clarkson: I don't see how this factory should return parametrized foos. Could you please explain how you get Foo<T> out of this? It seems to me this gives only unparametrized Foo. Isn't the T in make10 simply Foo here?
@ib84 I've fixed the code; I seem to have missed that Foo was parameterised when I wrote the answer originally.
7

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!

answered Feb 22, 2020 at 11:32

1 Comment

this works only if t is not null
6

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 .

Umpa
34212 silver badges17 bronze badges
answered Jan 17, 2013 at 21:22

1 Comment

This solution appears to require a generic super class like the other solutions here.
3

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];
 }
}
answered Jan 3, 2018 at 14:10

Comments

3

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() );
 }
answered Sep 7, 2019 at 12:22

Comments

2
 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
 }
 }
answered Apr 2, 2014 at 12:45

Comments

2

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();
answered Sep 20, 2017 at 2:44

Comments

2

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() );
 }
}
answered Oct 23, 2020 at 16:50

4 Comments

Which problem does this code actually solve? Change the method declaration to public static void printMethods(Object t) and it will do exactly the same. There is no "trick" in this answer but just an obsolete type parameter.
@Holger What if user wants to get the constructors of the object and call them to create new objects of that type?
Actually you can call getConstructures() on clazz to do it. Now the question is why the OP wants to get the T.class where he can just do t.getClass() ?
I asked what problem your code tries to solve. Asking "what if the user wants something else not shown in the answer" is not not an answer. Yes you can call getConstructors on a Class object. 1) but your code doesn’t 2) but it still doesn’t justify the use of the type parameter. The result of t.getClass() is Class<? extends Object>, whether you declare the parameter as T or Object. It makes no difference. You have an unchecked type cast (Class<T>) in your code. That’s not better than using getClass().getConstructor().newInstance() casting the result to whatever your want.
2

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.

answered May 19, 2022 at 14:40

Comments

1

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> {
}
answered Dec 5, 2016 at 10:43

Comments

1

You can use the springframework core inside an interface:

public interface IGetClass<T> {
 default Class<T> getTAsClass() {
 ResolvableType rType = ResolvableType.forClass(getClass());
 do {
 Optional<?> tClass = Arrays.stream(rType.getInterfaces())
 .filter(c -> IGetClass.class.equals(c.getRawClass()))
 .map(i -> i.resolveGeneric(0))
 .findFirst();
 if (tClass.isPresent()) {
 return (Class<T>) tClass.get();
 }
 rType = ResolvableType.forClass(rType.getRawClass()).getSuperType();
 } while (!rType.isInstance(Object.class));
 return null; // Should never be null
 } 
}

Usage:

public class Foo<T> implements IGetClass<T> {
 void bar() {
 Class<T> tClass = getTAsClass();
 }
}

I personally use it for XML conversion:

public interface IXmlFileConverter<T> implements IGetClass<T> {
 default T xmlFileConvert(File xmlFile) {
 Class<T> xmlClass = getTAsClass();
 try {
 JAXBContext jc = JAXBContext.newInstance(xmlClass);
 Unmarshaller u = jc.createUnmarshaller();
 return xmlClass.cast(u.unmarshal(xmlFile));
 } catch (Exception ex) {
 //...
 }
 }
}
answered Jan 15, 2024 at 7:18

Comments

0

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.

answered Nov 11, 2011 at 11:51

1 Comment

What do I do if items.isEmpty() is true?
0

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>
 }
}
answered Aug 14, 2019 at 12:05

Comments

0

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);
answered May 23, 2020 at 21:09

Comments

0

To be honest I used the solution with parameterized superclass constructor with the subclass type or with all type of reflection like java.lang.reflect.ParameterizedType, but it looks like ugly workaround for me.

I prefer to use an abstract method. I'm feeling like at least the contract between sub and superclass is more explicit.

public abstract class MySuperClass<T> {
 protected abstract T getSubClass();
 // Example of usage in superclass
 public String getName() {
 return getSubClass().getClass().getSimpleName();
 }
}
public class MySubClass extends MySuperClass<MySubClass> {
 @Override
 protected MySubClass getSubClass() {
 return this;
 }
 // ...
}
answered Aug 17, 2023 at 12:32

Comments

-4

I'm using workaround for this:

class MyClass extends Foo<T> {
....
}
MyClass myClassInstance = MyClass.class.newInstance();
answered Jun 27, 2017 at 8:45

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.