Java中的泛型类<t>?

时间:2016-09-22 10:43:51

标签: java generics

我刚刚转移到使用Java泛型,所以我不确定我是否甚至会问 正确的问题。

我正在尝试使用以下方法:

public <T> ResponseEntity<T> exchange(String url,
                                  HttpMethod method,
                                  HttpEntity<?> requestEntity,
                                  Class<T> responseType,
                                  Object... uriVariables)
                           throws RestClientException

对于<T>类型,我提供了Response<MyDTO>,因此我的方法调用如下:

ResponseEntity<Response<MyDTO>> re = exchange(...)

我无法弄清楚如何为Class<T> responseType参数提供正确的值?

我知道java中的泛型经历了类型擦除,所以你不能通过反射在运行时确定类型,但我知道我想要提供的确切类型。

我已经看到How to get a class instance of generics type T的许多变体,它们讨论了将类类型作为构造函数参数传递。

但我无法弄清楚如何制作Class<Response<MyDTO>>的实例。

有办法做到这一点吗?或者是否存在限制泛滥的限制?

3 个答案:

答案 0 :(得分:2)

Response<whatever>的班级是Response.class。但是,要告诉编译器您希望它成为Response<MyDTO>的类,具体而言您必须强制转换它:(Class<Response<MyDTO>>) (Object) Response.class。如果演员阵容让你觉得可疑......好吧,这是一件可疑的事情。

这将按预期工作,如果参数用于创建Response的新实例并且需要创建MyDTO的新实例(例如用户应该在调用exchange后设置它。但我无法想到任何其他情况。

答案 1 :(得分:2)

  

或者是否存在禁止此内容的泛型限制?

是。由于类型擦除,泛型类型的所有实例共享相同的运行时类,即

new Response<FooDto>().getClass() == new Response<BarDto>().getClass()

因为两个类型参数使用相同的类对象,所以它的类型不能约束该参数,即

new Response<FooDto>().getClass() 

的类型为

Class<? extends Response>

同样,Response<FooDto>.class无法编译,因为该特定类型没有类对象,只有一个类对象在所有Response实例之间共享。

理论上,你可以向编译器说谎类对象的类型:

Class c = Response.class
Class<Response<FooDto>> clazz = (Class<Response<FooDto>>) c

会编译,但不太可能在运行时执行您想要的操作,因为被调用的方法无法确定Response的类型参数。

这给我们留下了两个可能性:API设计人员搞砸了并且使这个API无法用于您的用例,或者您使用的API错误。查找该方法的重载,以不同的方式接受type参数的值,并验证您是否真的需要泛型。

答案 2 :(得分:0)

出于某种原因,采用Response<MyDTO>实例并使用getClass()的常用方法无法编译:

Response<MyDTO> response = new Response<MyDTO>(...);
Class<Response<MyDTO>> clazz = response.getClass(); 

如@meriton所述,它会导致cannot convert from Class<capture#1-of ? extends Response> to Class<Response<MyDTO>>

P.S。:将Class作为参数是非常不寻常的,我不知道他们需要什么。

P.P.S。:我测试了它,@ AlexeyRomanov和我的解决方案似乎都没有产生“一般化”的类:

import java.util.ArrayList;

class Main
{
    public static void main (String [] args)
    {
        System.out.println((Class<ArrayList<String>>)(Object)(ArrayList.class));
        System.out.println((new ArrayList<String>()).getClass()); 
    }
}

<强>输出

class java.util.ArrayList
class java.util.ArrayList

似乎两次泛型都丢失了。如果这不仅仅是Class.toString的问题,只需使用Response.class即可获得相同的结果。