简体   繁体   中英

Issue with passing generic type

I'm trying to do something like this :

public class ResponseProcessorFactory {

    public static <T> ResponseProcessor<T> newResponseProcessor(){
        return new GsonResponseProcessor<T>();
    }    
}

public class GsonResponseProcessor<T> implements ResponseProcessor<T> {

    protected T response;
    protected TypeToken typeToken;

    public GsonResponseProcessor() {
        this.typeToken = new TypeToken<T>(){};
    }

    @Override
    public void parse(String jsonString) throws JSONException, IOException {
            response = GsonHelper.getGsonInstance().fromJson(jsonString, typeToken.getType());
    }

    public T getResponse() {
        return response;
    }
}


private void ResponseProcessor getResponseProcessor(){
       return ResponseProcessorFactory<List<String>>.newResponseProcessor();
}

Now, whenever I invoke getResponseProcessor() , it doesn't return me the response processor for List<String> . Rather, it returns the default response processor for Object .

I'm sure, I'm missing some concept regarding generic. Can someone explain in detail ?

EDIT : The real usage is like this :

   public BaseRequestWithResponseProcessor<List<Dashboard>> getDashboards(Listener<List<Dashboard>> responseListener, ErrorListener errorListener) {
        String url = mBaseUrl + "/dashboard";

        ResponseProcessor<List<Dashboard>> responseProcessor = ResponseProcessorFactory.newResponseProcessor();

        AuthInfo authInfo = getAuthInfo();
        BaseRequestWithResponseProcessor<List<Dashboard>> request = new BaseRequestWithResponseProcessor<List<Dashboard>>(
                Method.GET, url, authInfo, null, responseProcessor, responseListener, errorListener);
        return request;
    }

In the GsonResponseProcessor constructor type erasure has happened and at runtime only one version of the method will exist with the type variable T converted to Object .

In Java only one version of generic methods and classes will exist, the type parameters only exist during compile-time and will be replaced by Object during run-time.

Type tokens must be constructed with a concrete type to capture the type information. This is the whole point with them, to capture type information at a place where the concrete type is known. The token can then be stored in variables and later be used to lookup objects or get hold of the type information with reflection.

The solution here is that the caller of getResponseProcessor who knows the concrete type creates the type token and passes it as a parameter. You could also pass in a Class object if that works in you situation. If you want to use generic classes as tokens however, as in your example with List<Dashboard> you will need a type token.

Something like this:

ResponseProcessor<List<String>> p = ResponseProcessorFactory.newResponseProcessor(new TypeToken<List<String>>() {});

You can work around the type erasure by passing in the class type as method parameter.

public class ResponseProcessorFactory {

    public static <T> ResponseProcessor<T> newResponseProcessor(Class<T> type){
        return new GsonResponseProcessor<T>(type);
    }    
}

public class GsonResponseProcessor<T> implements ResponseProcessor<T> {

    protected T response;
    protected TypeToken typeToken;

    public GsonResponseProcessor(Class<T> type) {
        this.typeToken = TypeToken.get(type);//depends on the API version

        //this.typeToken = new TypeToken<T>(type);
        //this.typeToken = TypeToken.of(type);
    }

    @Override
    public void parse(String jsonString) throws JSONException, IOException {
            response = GsonHelper.getGsonInstance().fromJson(jsonString, typeToken.getType());
    }

    public T getResponse() {
        return response;
    }
}

Have you tried changing the signature to the correct type, too?

private ResponseProcessor<List<String>> getResponseProcessor() {
    return ResponseProcessorFactory.newResponseProcessor();
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM