【问题标题】:Two generic types in java methodjava方法中的两种泛型
【发布时间】:2017-03-15 11:28:30
【问题描述】:

我正在使用 retrofit2 构建一些同步 json 代理。

我的服务器的响应总是格式:

{status:code, something:{complex object}}

所以我有:

public class BasicResponse<T> {

    private T data;

    @SerializedName("status")
    private String status;

 }

我的解析器有一个动态定义类型的映射,并根据服务器响应中“某事”的名称创建一个BasicResponse&lt;T&gt;

实际上一切正常,当“某事”返回我正在使用数组处理的对象列表时。

但我想将数组更改为任何类型的集合,我真的不想更改解析器,所以我创建了一个方法:

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&lt;User[]&gt; 并将其转换为BasicResponse&lt;List&lt;User&gt;&gt;

但由于List&lt;User&gt;User[] 不同,java 无法编译返回,我需要有两个可以相同或不同的泛型类型...

有可能吗?

【问题讨论】:

    标签: java generics retrofit2


    【解决方案1】:

    因此,如果我理解正确,您希望一个方法能够处理数组和原子元素类型的 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));
    }
    

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多