How do I retrieve the Class for a Parameterized Class

Marcus MacWilliam :

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 generics 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 a .class as a parameter to the constructor, and the unmarshall method automatically casts the return object.

I need to know the Class of T to pass to the newInstance() method, and to invoke the cast() method. i.e. T.class or T.getClass().

In my example I am attempting to initialise the clazz member, during the constructor, so that I can use it in both locations.

I have tried the following:

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

However getClass().getGenericSuperclass() returns an object which cannot be cast into a ParameterizedType. I cannot use any third party reflection libraries, I need to stick to the standard mechanisms inside the Jdk.

Valentin Ruano :

Actually you are extremely close to the actual solution... your first version of the code is quite close to what you need:

From:

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

To:

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

A single ? to T change would do the trick.

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=476830&siteId=1