Java泛型中的通配符无法编译

4
我制作了这个简化的代码示例,但它无法编译:
public class Example {

    public static void main(String[] args) {
        Callback<BalanceResponse> balanceRequestCaller = new Callback<BalanceResponse>() {
            @Override
            public void onResponse(BalanceResponse response) {}

            @Override
            public void onFailure(String error, int code) {}

            @Override
            public void onFailure(Throwable t) {}
        };

        BalanceRequest breq = new BalanceRequest();

        Interceptor interceptor = new Interceptor(balanceRequestCaller);

        breq.startRequest((Callback<BaseResponse>) interceptor); //compile-time error!!!
    }


    public static class Interceptor implements Callback<BaseResponse> {

        public Interceptor(Callback<? extends BaseResponse> originalCaller) {
            this.originalCaller = originalCaller;
        }

        private Callback<? extends BaseResponse> originalCaller;

        @Override
        public void onResponse(BaseResponse response) {
            //do some interception stuff

            if (response instanceof BalanceResponse) {
                ((Callback<BalanceResponse>) originalCaller).onResponse((BalanceResponse) response);
            } else if (response instanceof SubscriptionResponse) {
                ((Callback<SubscriptionResponse>) originalCaller).onResponse((SubscriptionResponse) response);
            }
        }

        @Override
        public void onFailure(String error, int code) {}

        @Override
        public void onFailure(Throwable t) {}
    }

    public interface Request<T extends BaseResponse> {
        void startRequest(Callback<T> callback);
    }

    public static class BalanceRequest implements Request<BalanceResponse> {
        @Override
        public void startRequest(Callback<BalanceResponse> callback) {}
    }

    public static class SubscriptionRequest implements Request<SubscriptionResponse> {
        @Override
        public void startRequest(Callback<SubscriptionResponse> callback) {}
    }

    public static class BaseResponse {
        public String status;
    }

    public static class BalanceResponse extends BaseResponse {

    }

    public static class SubscriptionResponse extends BaseResponse {

    }

    public interface Callback<T> {
        void onResponse(T response);
        void onFailure(String error, int code);
        void onFailure(Throwable t);
    }
}

我想做的是创建一个拦截器,用于拦截回调函数,对响应进行一些操作,然后将其传递给原始回调函数。
我想制作一个通用的拦截器,可以拦截任何类型为“Callback <?extends BaseResponse>”的回调函数。
顺便说一下,NetBeans给出的编译时错误是:
incompatible types: Callback<BaseResponse> cannot be converted to Callback<BalanceResponse>

给我一些建议,如何让这个工作起来?

2个回答

3

你应该在你的类Interceptor上定义一个类型参数,以防止编译错误并避免在方法onResponse中进行显式转换,这通常是设计问题的证明。

带有类型参数的你的拦截器类:

public static class Interceptor<T extends BaseResponse> implements Callback<T> {

    public Interceptor(Callback<T> originalCaller) {
        this.originalCaller = originalCaller;
    }

    private Callback<T> originalCaller;

    @Override
    public void onResponse(T response) {
        originalCaller.onResponse(response);
    }

    ...
}

您可以实例化它并按以下方式使用:
Interceptor<BalanceResponse> interceptor = new Interceptor<>(balanceRequestCaller);
breq.startRequest(interceptor);

1

startRequest()的签名更改为

void startRequest(Callback<? super T> callback);

这使得它可以接受更通用的回调,而不仅仅是最狭窄的类型。更多信息请参见PECS是什么(生产者扩展消费者超级)? 编辑:@teppic的答案是更好的解决方案,除非您必须重用单个拦截器实例以处理不同的请求类型。如果是这种情况,您仍然可以将样板代码减少到一个委托。
@Override
public void onResponse(BaseResponse response) {
    //do some interception stuff
    ((Callback<BaseResponse>)originalCaller).onResponse(response);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接