Java 带有通配符的泛型无法编译
Java generics with wildcard not compiling
我做了这个我真实代码的简化示例,它没有编译:
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);
}
}
我想做的是制作一个 Interceptor
来拦截回调,对响应做一些处理,然后将其传递给原始回调。
我想制作一个通用的 Interceptor
,它可以拦截 Callback<? extends BaseResponse>
的任何回调。
顺便说一句,我从 NetBeans 得到的编译时错误是
incompatible types: Callback<BaseResponse> cannot be converted to Callback<BalanceResponse>
请给我建议,我怎样才能完成这项工作?
您应该在 class Interceptor
上定义一个 类型参数 以防止编译错误并避免在方法中进行显式转换 onResponse
这通常是设计问题的证明。
您的拦截器 class 具有 类型参数:
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);
将startRequest()
签名的签名改为
void startRequest(Callback<? super T> callback);
这允许它接受更通用的回调,而不是只需要最窄的类型。有关详细信息,请参阅 What is PECS (Producer Extends Consumer Super)?
编辑: 是更好的解决方案,除非您必须为不同的请求类型重用单个 Interceptor
实例。如果是这种情况,您仍然可以将样板文件减少为单个委托:
@Override
public void onResponse(BaseResponse response) {
//do some interception stuff
((Callback<BaseResponse>)originalCaller).onResponse(response);
}
我做了这个我真实代码的简化示例,它没有编译:
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);
}
}
我想做的是制作一个 Interceptor
来拦截回调,对响应做一些处理,然后将其传递给原始回调。
我想制作一个通用的 Interceptor
,它可以拦截 Callback<? extends BaseResponse>
的任何回调。
顺便说一句,我从 NetBeans 得到的编译时错误是
incompatible types: Callback<BaseResponse> cannot be converted to Callback<BalanceResponse>
请给我建议,我怎样才能完成这项工作?
您应该在 class Interceptor
上定义一个 类型参数 以防止编译错误并避免在方法中进行显式转换 onResponse
这通常是设计问题的证明。
您的拦截器 class 具有 类型参数:
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);
将startRequest()
签名的签名改为
void startRequest(Callback<? super T> callback);
这允许它接受更通用的回调,而不是只需要最窄的类型。有关详细信息,请参阅 What is PECS (Producer Extends Consumer Super)?
编辑:Interceptor
实例。如果是这种情况,您仍然可以将样板文件减少为单个委托:
@Override
public void onResponse(BaseResponse response) {
//do some interception stuff
((Callback<BaseResponse>)originalCaller).onResponse(response);
}