我正在尝试编写一个泛型方法,因此我可以将它重用于多个请求和响应类型。这是非通用方法
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 {
答案 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);
无需传递类类型。
这样我们就不必添加额外的参数或更改方法定义。