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

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP

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.





There is no such thing as C<D>.class. What precisely are you trying to achieve?
– JB Nizet
51 mins ago





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

Comments

Popular posts from this blog

Executable numpy error

Trying to Print Gridster Items to PDF without overlapping contents

Mass disable jenkins jobs