How to get a class for a parameterized class

Consider the following code:

public class Context { private final Class<?> clazz; private final String resource; private final com.thirdparty.Context context; public Context(final String resource, final Class<?> clazz) { this.clazz = clazz; this.resource = resource; this.context = com.thirdparty.Context.newInstance(this.clazz); } public String marshall(final Object element) { return this.context.marshall(element); } public Object unmarshall(final String element) { return this.context.unmarshall(element); } } Context context = new Context("request.xsd", Request.class); // Marshall Request request = new Request(); String xml = context.marshall(request); // Unmarshall Request roundTrip = Request.cast(context.unmarshall(xml)); 

I am trying to replace it with a generalized version of the Context class:

 public class Context<T> { private final Class<T> clazz; private final String resource; private final com.thirdparty.Context context; public Context(final String resource) { this.clazz = initHere(); // <== HOW ?? this.resource = resource; this.context = com.thirdparty.Context.newInstance(this.clazz); } public String marshall(final T element) { return this.context.marshall(element); } public T unmarshall(final String element) { return this.clazz.cast(this.context.unmarshall(element)); } } Context<Request> context = new Context<>("request.xsd"); // Marshall Request request = new Request(); String xml = context.marshall(request); // Unmarshall Request roundTrip = context.unmarshall(xml); 

Thus, I do not pass .class as a parameter to the constructor, and the unmarshall method automatically returns the returned object.

I need to know the class T to go to the newInstance () method and call the cast () method. those. T.class or T.getClass ().

In my example, I am trying to initialize the clazz member during the constructor so that I can use it in both places.

I tried the following:

 this.clazz = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0]; 

However, getClass (). getGenericSuperclass () returns an object that cannot be passed to ParameterizedType. I cannot use third-party reflection libraries, I need to stick to the standard mechanisms inside Jdk.

+5
source share
3 answers

Actually, you are very close to the real solution ... your first version of the code is pretty close to what you need:

From:

 public Context(final String resource, final Class<?> clazz) { //... } 

To:

 public Context(final String resource, final Class<T> clazz) { // ... } 

The only change ? to T will do the trick.

+1
source

You cannot do this. In your case, the generic type T is associated with your instance. Reflection data is bound to a class, and your class does not define type T.

The code you are trying to use only works if you define the class where T is configured.

 public class RequestContext extends Context<Request> {} 

If you are using an instance of this class, then your code should work.

+4
source

You cannot do this in the constructor. If you do not pass an instance of Class to the constructor, there is no way for the Context class to know what object it is dealing with.

Take a look here: http://www.angelikalanger.com/GenericsFAQ/JavaGenericsFAQ.html#Reflection

To determine the type and the general type, you need an object. And you have no object.

Is there a specific reason why you cannot add the Class parameter to the constructor? If there is, you, for example, do not explain.

+3
source

Source: https://habr.com/ru/post/1274661/


All Articles