How to get a class instance of type Foo (Foo.class not work) [duplicate]


How to get a class instance of type Foo<T> (Foo<T>.class not work) [duplicate]
This question already has an answer here:
I would like to get the class of Foo< T >.class (exactly Foo < T>, neither T.class nor Foo.class)
public class A extends B<C<D>>
public A()
super(C<D>.class); // not work
On StackOverflow has a instruction for obtaining generic class by injecting into constructor but it's not my case because C< D>.class (e.g List<
String>.class) is syntax error. At here it seems relate to syntax more than code structure.
To show more detail, higher level view, the original code is the following, its HATEOAS module in Spring framework:
public class CustomerGroupResourceAssembler extends ResourceAssemblerSupport<CustomerGroup, CustomerGroupResource>
public CustomerGroupResourceAssembler()
super(CustomerGroupController.class, CustomerGroupResource.class);
public class CustomerGroupResource extends ResourceSupport
private CustomerGroup data;
But now I want to parameterize the CustomerGroupResource to
public class Resource<T> extends ResourceSupport
private T data;
and then
public class CustomerGroupResourceAssembler extends ResourceAssemblerSupport<CustomerGroup, Resource<CustomerGroup>>
public CustomerGroupResourceAssembler()
super(CustomerGroupController.class, Resource<CustomerGroup>.class); // not work here, even Resource.class
This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.
I would like to get class of C, but it's a type parameter one. So when a method needs class of C (maybe include that type parameter because when I pass C.class it was not accepted) . So I dont know how to get that.
– ngocchien
44 mins ago
That I understand. But at a much higher level, what are you trying to achieve. What are you using this class instance for? Why is it needed? To do what?
– JB Nizet
43 mins ago
Thank you JB Nizet, I edited my question for more detail. Please read again!
– ngocchien
21 mins ago
And you still haven't explained why ResourceAssemblerSupport needs class instances and what it does with them.
– JB Nizet
18 mins ago
2 Answers
2
Unfortunately what you are trying to do is impossible due to type erasure.
Information about generic types is only avalilable at compile time and not at run time. This is one of biggest limitations of using generics in Java. The reason why it was done like this is to preserve backwards compatibility.
See Java generics type erasure: when and what happens?
Due to type erasure, the generic only applies at compile time and doesn't mean anything at runtime. What you can do is
public class A extends B<C<D>>
public A()
super((Class<C<D>>) C.class);
However, you won't be able to determine the type of D
at runtime. You can use reflection to get the super type however.
D
public class Main
public static abstract class B<X>
protected B()
Type type = getClass().getGenericSuperclass();
System.out.println(type);
public static class A extends B<Supplier<String>>
public A()
public static void main(String args)
new A();
prints
Main.Main$B<java.util.function.Supplier<java.lang.String>>
EDIT For your specific example you can do.
import java.lang.reflect.Type;
public interface Main
class ResourceSupport
class CustomerGroup
public class Resource<T> extends ResourceSupport
private T data;
abstract class ResourceAssemblerSupport<C, R>
protected ResourceAssemblerSupport()
Type type = getClass().getGenericSuperclass();
System.out.println(type);
ParameterizedType pt = (ParameterizedType) type;
Type actualTypeArguments = pt.getActualTypeArguments();
Class first = (Class) actualTypeArguments[0];
ParameterizedType second = (ParameterizedType) actualTypeArguments[1];
System.out.println(pt.getRawType() + " <" + first + ", " + second + ">");
public class CustomerGroupResourceAssembler extends ResourceAssemblerSupport<CustomerGroup, Resource<CustomerGroup>>
public CustomerGroupResourceAssembler()
public static void main(String args)
new CustomerGroupResourceAssembler();
prints
Main.Main$ResourceAssemblerSupport<Main$CustomerGroup, Main.Main$Resource<Main$CustomerGroup>>
class Main$ResourceAssemblerSupport <class Main$CustomerGroup, Main.Main$Resource<Main$CustomerGroup>>
A generic way to do what you want is to use a helper function, however I think this isn't needed in your case.
public static void main(String args)
System.out.println(new ClassType<List<String>>() .getType());
interface ClassType<T>
default Type getType()
ParameterizedType type = (ParameterizedType) getClass().getGenericInterfaces()[0];
return type.getActualTypeArguments()[0];
prints
java.util.List<java.lang.String>
@downvoter any idea why?
– Peter Lawrey
23 mins ago
Upvote for your enthusiasm (downvote not me). I'll give it a try. Thanks you so much.
– ngocchien
9 mins ago
There is no such thing as C<D>.class. What precisely are you trying to achieve?
– JB Nizet
51 mins ago