简体   繁体   English

传递泛型类型的问题

[英]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> . 现在,每当我调用getResponseProcessor() ,它都不会向我返回List<String>的响应处理器。 Rather, it returns the default response processor for Object . 而是返回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 . GsonResponseProcessor构造函数中,发生了类型擦除 ,并且在运行时仅存在该方法的一个版本,类型变量T转换为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. 在Java中,仅存在一种版本的通用方法和类,类型参数仅在编译时存在,并且在运行时将由Object替换。

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. 这里的解决方案是知道具体类型的getResponseProcessor的调用者创建类型令牌并将其作为参数传递。 You could also pass in a Class object if that works in you situation. 如果在您的情况下可行,也可以传入Class对象。 If you want to use generic classes as tokens however, as in your example with List<Dashboard> you will need a type token. 但是,如果要使用通用类作为标记,例如在List<Dashboard>示例中,则需要类型标记。

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();
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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