如何在泛型方法中传递<t>的Class类型

时间:2017-10-26 10:26:54

标签: java

我正在尝试编写一个泛型方法,因此我可以将它重用于多个请求和响应类型。这是非通用方法

 public ReservationBookingResponse invokeService(String endPoint, ReservationBookingRequest reservationBookingRequest, HttpServletRequest httpServletRequest) throws  APIException {

ResponseEntity<ReservationBookingResponse> response = null;
try {  
    String authToken = getAuthToken(restTemplate, httpServletRequest);
    HttpEntity<ReservationBookingRequest> entity = new HttpEntity<ReservationBookingRequest>(reservationBookingRequest, addAuthorizationHeader(authToken));
    response = restTemplate.postForEntity(endPoint, entity, ReservationBookingResponse.class);  

} catch (Exception e) {
    throw new  APIException(e);
}

return response.getBody();
}

这是我写的通用方法

public default T invoke(String endPoint, K requestBean, HttpServletRequest httpServletRequest) throws  APIException {

    RestTemplate restTemplate=new RestTemplate();
    ResponseEntity<T> response = null;
    try {
            String authToken = getAuthToken(restTemplate, httpServletRequest);
            HttpEntity<K> entity   = new HttpEntity<K>(requestBean, addAuthorizationHeader(authToken));
        response = restTemplate.postForEntity(endPoint, entity, T);

    } catch (Exception e) {
        throw new  APIException(e);
    }
    return  response.getBody();
    }

现在问题出在response = restTemplate.postForEntity(endPoint, entity, T); 我在非通用(前)方法response = restTemplate.postForEntity(endPoint, entity, ReservationBookingResponse.class);中得到一个异常“T无法解析为类型”这很好。

现在我不能做 T.class ,因为它是不允许的。有人可以告诉我如何将Class<T>传递给方法。

这是postforEntity方法所期望的

@Override
    public <T> ResponseEntity<T> postForEntity(String url, Object request, Class<T> responseType, Object... uriVariables)
            throws RestClientException {

3 个答案:

答案 0 :(得分:1)

调用者需要在某个时候给你Class<T>

最直接的方法是在调用invoke时要求调用者提供类。这是Piotr Wilkin所建议的以及你在答案中所做的。然而,它创造了比所需更多的样板,并且有更好的选择。

由于T是整个对象的通用,因此您可以将Class<T>提供给构造函数,例如:

private final Class<T> type; // some prefer naming like clazz

public MyClassThatHasTheInvokeMethod(Class<T> type) { /* set the field(s) here */ }

然后,您可以轻松地将type提供给需要Class<T>的任何方法调用。

答案 1 :(得分:0)

你做不到。

由于类型擦除,类型T基本上不会在运行时以任何方式提供。您可以检索类型T的唯一情况是在非泛型类中继承了泛型类的特定情况(即Foo extends Bar<Something>),在这种情况下您可以检索Something

在所有其他情况下,遗憾的是,您必须使用样板 - 显式传递类对象。如果您的任何构造函数参数是T类型的对象,则可以使用.getClass()来避免使用样板,否则您必须手动传递该类。

答案 2 :(得分:0)

这是我必须做的才能使其工作,将类类型作为参数从调用方法传递。

快速修复解决方案-1

public  T postRequestToService(String endPoint, K requestBean, HttpServletRequest httpServletRequest, 
 Class<T> classType) throws  APIException {

 response = restTemplate.postForEntity(endPoint, entity, classType);

和调用方法

postRequestToService(endPoint+addOnAvailability, addOnAvailabilityRequest,
httpServletRequest, AddOnAvailabilityResponse.class);

然而,一个更好的解决方案是一个 - 解决方案-2

定义构造函数,即使这恰好是一个抽象类

public class PegasusService<K, T> {

    private Class<K> requestClass;
    private Class<T> responseClass;

     public PegasusService(Class<K> requestClass, Class<T> responseClass) {
this.requestClass = requestClass;
this.responseClass = responseClass;
}

并在子类中传递构造函数中的类类型。

   AddOnAvailabilityService() {
    super(AddOnAvailabilityRequest.class, AddOnAvailabilityResponse.class);
    }

所以这段代码工作正常response = restTemplate.postForEntity(endPoint, entity, responseClass);无需传递类类型。

这样我们就不必添加额外的参数或更改方法定义。