通用方法,等式约束

时间:2017-02-18 16:16:02

标签: java generics

您好我试图将通用方法实现为控制器基本方法,但是我无法理解的问题发生在泛型方法签名上。

<T> ResponseEntity<T> makeApiCall(String path, HttpMethod httpMethod, T body, boolean isAdmin){

        String sender = isAdmin ? adminHash : userHash;
        HttpHeaders headers = new HttpHeaders();
        headers.add("Authorization", sender);
        headers.add("Content-Type", "application/json");
        HttpEntity<T> entity = new HttpEntity<>(body,headers);
        ResponseEntity<T> responseEntity = restTemplate.exchange(path, HttpMethod.POST, entity, body.getClass());
        return responseEntity;
}

我目前的编译错误如下:

Incompatible equality constraint: T and capture of ? extends Object

2 个答案:

答案 0 :(得分:4)

您没有准确说出问题发生的位置,但我认为这会在restTemplate.exchange(调用中发生,因为将body.getClass()作为参数传递。这是因为body.getClass()的返回类型为Class<? extends Object>as in the Javadoc

  

实际结果类型为Class<? extends |X|>,其中|X|是删除调用getClass的表达式的静态类型

问题在于,您无法保证body具体为T - 它可能是T的子类。因此,body.getClass()的结果可能不是Class<T>

如果您想要是类型安全的,则需要将其作为附加参数传递给方法。

<T> ResponseEntity<T> makeApiCall(
    String path, HttpMethod httpMethod, T body, Class<T> bodyClass, 
    boolean isAdmin){
  // ...
  ResponseEntity<T> responseEntity =
      restTemplate.exchange(
          path, HttpMethod.POST, entity, bodyClass);
  // ...
}

请注意,获取Class<T>的唯一方法是使用类文字,例如如果String.classT,则为String。这排除了使用通用的体型,因为没有通用的类文字。

答案 1 :(得分:2)

您需要cast body.getClass()Class<T>

@SuppressWarnings("unchecked")
<T> ResponseEntity<T> makeApiCall(String path, HttpMethod httpMethod, T body, boolean isAdmin){

    String sender = isAdmin ? adminHash : userHash;

    HttpHeaders headers = new HttpHeaders();
    headers.add("Authorization", sender);
    headers.add("Content-Type", "application/json");
    HttpEntity<T> entity = new HttpEntity<>(body,headers);
    ResponseEntity<T> responseEntity = restTemplate.exchange(path, HttpMethod.POST, entity, (Class<T>) body.getClass());
    return responseEntity;
}

要使其类型安全,您需要明确地将类对象作为参数传递:

<T> ResponseEntity<T> makeApiCall(String path, HttpMethod httpMethod, T body, Class<T> clazz, boolean isAdmin){
String sender = isAdmin ? adminHash : userHash;

    HttpHeaders headers = new HttpHeaders();
    headers.add("Authorization", sender);
    headers.add("Content-Type", "application/json");
    HttpEntity<T> entity = new HttpEntity<>(body,headers);
    ResponseEntity<T> responseEntity = restTemplate.exchange(path, HttpMethod.POST, entity, clazz);
    return responseEntity;
}