2016-09-22 51 views
3

我刚刚转向使用Java泛型,因此我不确定是否我要求 是正确的问题。类<T>为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>>的实例。

有没有办法做到这一点?或者是否有禁忌的仿制药限制?

回答

2

或者在仿制药中是否存在禁忌的限制?

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

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

因为同一类对象用于两个类型参数,其类型不能约束该参数,即

new Response<FooDto>().getClass() 

的类型是

Class<? extends Response> 

同样,Response<FooDto>.class不编译的,因为没有用于该特定类型的无级对象,只有一类对象S在所有Response实例中都有。

从理论上讲,你就可以躺在约类对象的类型,编译器:这将汇编

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

,但不太可能做你想做的在运行时,因为被调用的方法将无法确定Response的类型参数。

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

+0

我实际上正在考虑一个特定的场景,它应该做你想做的事情(并且编辑我的答案以表明清楚),但是否则,是的。 –

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作为一个参数是非常不寻常的,我不知道他们需要什么。

PPS:我测试了它和两@ 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即可得到相同的结果。

+0

可能调用'newInstance()'或'getConstructor(...)。newInstance(...)'。 –

+0

您的代码无法编译:“类型不匹配:无法从类转换为类<响应>” – meriton

+0

@meriton您是对的,我编辑了我的答案。 –

2

Response<whatever>的等级是Response.class。但是,要告诉编译器,您希望它是Response<MyDTO>的类,具体而言,您必须将其转换为:(Class<Response<MyDTO>>) (Object) Response.class。如果演员对你产生怀疑......好吧,这是一件可疑的事。

这将实现预期的是,如果该参数被用来创建Response一个新实例,不需要创建MyDTO一个新实例(例如,假设用户调用exchange后将其设置)。但我想不出其他情况。