我正在使用retrofit2构建一些同步的json代理。
我的服务器的响应始终采用以下格式:
{status:code, something:{complex object}}
所以我有:
public class BasicResponse<T> {
private T data;
@SerializedName("status")
private String status;
}
我的解析器有一个动态定义类型的地图,并根据服务器响应中“某事”的名称创建BasicResponse<T>
实际上一切正常,当“某事”返回我正在使用数组工作的对象列表时。
但我想将数组更改为任何类型的集合,我真的不想更改解析器,所以我创建了一个方法:
private <U> BasicResponse<U> handleResponse(Response<? extends BasicResponse<U>> resp){
BasicResponse handledResponse = null;
if (resp != null && resp.isSuccessful() && resp.body() != null) {
resp.body();
if(handledResponse.getData().getClass().isArray())
handledResponse.setData(Arrays.asList(handledResponse.getData()));
//a lot of others stuff
return handledResponse;
}
在这种方法中,我希望得到一些“resp”作为BasicResponse<User[]>
并在BasicResponse<List<User>>
上转换
但由于List<User>
与User[]
不同,java无法编译返回,我需要有两个可以或不相同的泛型类型...
有可能吗?
答案 0 :(得分:0)
因此,如果我理解正确,您希望单个方法能够处理混合的数组和原子元素类型的BasicResponse输入,但返回始终是List类型的BasicResponse。
您不能使用类型参数(代码中的U)将组件类型从输入绑定到返回。原因是X和X [](无论X是什么)都没有共同的超类,可以排除任何其他类型的响应数据。
解决此问题的一种方法是提供将输入类型转换为输出类型的lambda,如下所示:
private <U,V> BasicResponse<U> handleResponse(final Response<BasicResponse<V>> resp, final Function<U, V> cast) {
if (resp == null || !resp.isSuccessful() || resp.body() == null)
return null;
else
return new BasicResponse<>(cast.apply(resp.body().getData()));
}
...
Response<BasicResponse<String[]>> arrayResp = ...;
BasicResponse<List<String>> listBasicResp =
handleResponse(arrayResponse, (v) -> Arrays.asList(v));
...
Response<BasicResponse<String>> atomicResp = ...;
BasicResonse<List<String>> listBasicResp2 =
handleResponse(atomicResponse, (v) -> Collections.singletonList(v));
请注意,只要有一个提供适当的lambda来进行转换,就可以为输入和结果基本响应混合使用不同的组件类型。我会说,大部分时间不应该是一个问题,事实上,即使你不方便一个方法,也没有任何东西会阻止用户代码进行这样的翻译。
如果要为绑定组件类型的特定两种情况提供预制方法,则可以简单地添加一些额外的handleResponse方法,这些方法在上面的方法中委派并提供适当的lambda:
private <U> BasicResponse<List<U>> handleSingleObjectResponse(final Response<BasicResponse<U>> resp) {
return handleResponse(resp, (v) -> Collections.singletonList(v));
}
private <U> BasicResponse<List<U>> handleArrayResponse(final Response<BasicResponse<U[]>> resp) {
return handleResponse(resp, (v) -> Arrays.asList(v));
}
请注意,您不能重载与擦除后相同的方法名称,它们共享签名:(响应)。