因此,在深入研究了反射的深渊之后,我发现您可以实现 ParameterizedType(因为它是一个接口)并使用它来生成与改造不同的调用。
在我的 CallAdapter.Factory 实现中,我创建了这种类型:
private static class AwesomeResponseType implements ParameterizedType {
private final Type innerType;
public BrainResponseType(Type innerType) {
this.innerType = innerType;
}
@Override
public Type[] getActualTypeArguments() {
return new Type[] {innerType};
}
@Override
public Type getRawType() {
return AwesomeResponse.class;
}
@Override
public Type getOwnerType() {
return null;
}
}
在创建适配器时,我会像这样注入内部类型:
final Type innerType = getParameterUpperBound(0, (ParameterizedType) returnType);
ParameterizedType parameterizedType = new AwesomeResponseType(innerType);
并使用parameterizedType 创建自定义CallAdapter,如下所示:
private static class AwesomeCallAdapter<T> implements CallAdapter<AwesomeCall<?>> {
private final Type responseType;
private AwesomeCallAdapter(Type responseType) {
this.responseType = responseType;
}
@Override
public Type responseType() {
return responseType;
}
@SuppressWarnings("unchecked")
@Override
public <R> AwesomeCall<T> adapt(Call<R> call) {
return new AwesomeCall<>((Call<AwesomeResponse<T>>)call);
}
}
AwesomeCall 现在可以愉快地处理需要 AwesomeResponse 的调用:
public class AwesomeCall<T> {
private final Call<AwesomeResponse<T>> call;
public AwesomeCall(Call<AwesomeResponse<T>> call) {
this.call = call;
}
public AwesomeResponse<T> execute() throws IOException {
Response<BrainResponse<T>> response = call.execute();
return response.isSuccessful() ? response.body() : errorResponseFrom(response);
}
private AwesomeResponse<T> errorResponseFrom(Response<AwesomeResponse<T>> response) {
return new AwesomeResponse<>(null, new AwesomeError(response.message()));
}
}
如果你使用 Guava,我相信你不必实现ParameterizedType。 TypeToken 有一个 API 可以做到这一点:
TypeToken.of(AwesomeResponse.class).where(new TypeParameter<T>() {}, innerType).getType();
但遗憾的是,Gson 中的 TypeToken 不支持该功能 :(