Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I retrieve the Class for a Parameterized Class

Tags:

java

generics

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.

like image 928
Marcus MacWilliam Avatar asked Jan 12 '18 14:01

Marcus MacWilliam


People also ask

How do you find the class type from generics?

You can get around the superfluous reference by providing a generic static factory method. Something like public static <T> GenericClass<T> of(Class<T> type) {...} and then call it as such: GenericClass<String> var = GenericClass. of(String. class) .

What is parameterized class in Java?

The type parameter section of a generic class can have one or more type parameters separated by commas. These classes are known as parameterized classes or parameterized types because they accept one or more parameters.

What is getClass method in Java?

The Java Object getClass() method returns the class name of the object. The syntax of the getClass() method is: object.getClass()


1 Answers

You can't do that. In your case, the Generic Type T is linked to your instance. Reflection data are bound to Class, and your class doesn't define the type T.

The code you are trying to use works only if you define a class where T is set up.

public class RequestContext extends Context<Request> {}

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

like image 159
Genu Avatar answered Oct 05 '22 09:10

Genu