我刚刚转移到使用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>>
的实例。
有办法做到这一点吗?或者是否存在限制泛滥的限制?
答案 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
即可获得相同的结果。