Java 如何在泛型方法中传递的类类型

Java 如何在泛型方法中传递的类类型,java,Java,我正在尝试编写一个通用方法,以便可以将其用于多种请求和响应类型。这是非泛型方法 public ReservationBookingResponse invokeService(String endPoint, ReservationBookingRequest reservationBookingRequest, HttpServletRequest httpServletRequest) throws APIException { ResponseEntity<Reservatio

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

 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();
}
调用方需要在某个时刻为您提供该类

最直接的方法是在调用invoke时要求调用方提供类。这是Piotr Wilkin的建议,也是你在回答中所做的。然而,它创建的样板文件比需要的要多,而且还有更好的选择

由于T是整个对象的泛型,因此可以向构造函数提供类,如:

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

public MyClassThatHasTheInvokeMethod(Class<T> type) { /* set the field(s) here */ }
然后,您可以轻松地为任何需要类的方法调用提供类型。

您不能

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


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

这就是我必须做的,要使其工作,请将该类类型作为调用方法的参数传递

快速解决方案-1

然而,一个更好的解决方案低于一个解决方案-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;
}
因此,这段代码运行良好,response=restemplate.postForEntityendPoint,entity,responseClass;不需要传递类类型


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

您必须拥有实际的类对象,这是毫无疑问的。所以这取决于你从哪里得到T——你必须把对类的引用保存在同一个地方。例如,在构造函数或方法签名中,您可以从类型为T的变量中获取类对象。您只需对其调用getClass并强制转换结果。但是,它不是类型安全的,因为不能保证它是同一个类-它也可以是一个子类型。我只记得用枚举做过。不管怎么说,这里的情况不太一样——postEntity是创建对象的地方。谢谢,这就是我没有问题的地方。那么,如果它回答了您的问题,请随意接受。事实上,如果您在构造函数中为Bar实例提供Something.class,或者在Foo的情况下,您可以有一个调用superSomething.class的无参数构造函数,那么您可以接受。在这两种情况下,您都不需要为每个方法调用提供T类。这是一个失败者的变体。这是一个具有泛型类型参数的类的方法,但您必须在每次调用中提供T类。如果您将其提供给我不知道其名称的类的构造函数,因为您将其从代码中排除,这对调用方来说会更好。它是一个抽象类,所以我没有定义任何构造函数。这是一个糟糕的借口,抽象类可以有受保护的构造函数。当然,没有子类化就无法实例化。这就是我创建的构造函数公共类PegasusService{private K requestClass;private t responseClass;public PegasusService K,t t{This.setRequestClassk;This.setResponseClasst;}在子类AddOnAvailabilityServiceAddOnAvailabilityRequest k中,AddOnAvailabilityResponse t{superk,t;}然而response=restemplate.postForEntityendPoint,entity,responseClass;仍然给我相同的错误您不应该提供实例本身,您应该向构造函数提供类。就像AddOnAvailabilityResponse.class一样。
private final Class<T> type; // some prefer naming like clazz

public MyClassThatHasTheInvokeMethod(Class<T> type) { /* set the field(s) here */ }
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);
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);
    }