2017-02-18 70 views
2

你好我試圖實現一個通用的方法作爲控制器的基本方法,但我不明白的問題發生在genereric方法syngature。通用方法,等式約束

<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; 
    } 

編譯錯誤我currenty有如下:

Incompatible equality constraint: T and capture of ? extends Object 

回答

3

您不能確切地說問題出現在哪裏,但我認爲這將發生在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.class如果TString。這排除了通用體類型的使用,因爲沒有通用類文字。

+0

「獲得類的唯一方法是使用類字面值,例如,如果T是字符串,則使用String.class,這排除了使用通用體類型,因爲沒有通用類文字」似乎與自身矛盾。無論如何,在編譯時編譯器可以找出泛型類型。那麼將'getClass()'結果賦給一個'Class '變量怎麼辦? –

+1

@LewBloch:我認爲他的意思是'T'必須是一個可確定的類型。否則,如果'T'是一個參數化的類型,比如'Foo ',那麼你將不得不提供一個'Class >',這並不安全。 – newacct

1

您需要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; 
} 
+1

泛型轉換引發您應該處理的警告。 –