java方法

时间:2017-03-15 11:28:30

标签: java generics retrofit2

我正在使用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无法编译返回,我需要有两个可以或不相同的泛型类型...

有可能吗?

1 个答案:

答案 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));
}

请注意,您不能重载与擦除后相同的方法名称,它们共享签名:(响应)。