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.
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.