Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Class of generic class

Tags:

java

I might blind some people here but I will fire anyway.

I know I can do:

Class<Response> c = Response.class;

To get the class of the object. Assuming that the Response object is Response<T> I want to do something like the following

Class<Class<User>> c =  Response<User>.class;

My full problem:

public class RequestHelper<T> extends AsyncTask<String, Response, T> {

    @Override
    protected T doInBackground(String... strings) {
       ...
       Response <T> r = objectMapper.readValue( result, Response.class );
       return r .getResponse();
    }
}

//and

public class Response <R> {
    private R response;
    public R getResponse() {
        return response;
    }
}

But above the parameter has not been specified in the assignment. In theory the correct way would require:

public class RequestHelper<T> extends AsyncTask<String, Response, T> {

    @Override
    protected T doInBackground(String... strings) {
       ...
       Response <T> r = objectMapper.readValue( result, Response <T>.class );
       return r.getResponse();
    }
}

But that generates a "Cannot select from parameterized type" lint error.

Alternatively I could pass the class in the constructor:

public class RequestHelper<T> extends AsyncTask<String, Response, T> {

    ....
    public RequestHelper(Class<Class<T>> tClass){
         this.tClass = tclass;
    }

    @Override
    protected T doInBackground(String... strings) {
       ...
       Response <T> r = objectMapper.readValue( result, tclass );
       return r.getResponse();
    }
}

// where the init of the class would have been:

 new RequestHelper<User>( Response<User>.class );
like image 719
Diolor Avatar asked Sep 26 '14 19:09

Diolor


1 Answers

As the comments suggest, there is no such thing as

Class<GenericType<GenericArgument>>

Or rather, it doesn't do what you might think it does. Each type declaration (class, interface, enum, primitive) gets a single Class instance, whether it is generic or not.

As such, even if you have a reference of type Class<GenericType<ArgumentOne>> and another of type Class<GenericType<ArgumentTwo>>, the instance they are referencing will be exactly the same. What's more, there will be absolutely no way to query the type argument type.

You seem to be using Jackson's ObjectMapper. It provides a kind of hack for getting generic type information in the form of type tokens. You can use a TypeReference or JavaType instance to represent generic types. Examples here and elsewhere around the Internet.

like image 117
Sotirios Delimanolis Avatar answered Sep 19 '22 14:09

Sotirios Delimanolis