2014-09-26 38 views
9

我可能會讓某些人失明,但我仍然會開槍。通用類的類別

我知道我可以做:

Class<Response> c = Response.class; 

要獲得對象的類。假設Response對象是Response<T>我想要做類似下面的

Class<Class<User>> c = Response<User>.class; 

我充滿問題:

public class RequestHelper<T> extends AsyncTask<String, Response, T> { 

    @Override 
    protected T doInBackground(String... strings) { 
     ... 
     Response <T> r = objectMapper.readValue(result, Response.class); 
     return r .getResponse(); 
    } 
} 

//and 

public class Response <R> { 
    private R response; 
    public R getResponse() { 
     return response; 
    } 
} 

但參數在上面的分配還沒有被指定。理論上,正確的方法將需要:

public class RequestHelper<T> extends AsyncTask<String, Response, T> { 

    @Override 
    protected T doInBackground(String... strings) { 
     ... 
     Response <T> r = objectMapper.readValue(result, Response <T>.class); 
     return r.getResponse(); 
    } 
} 

但是,這會生成「無法從參數化類型中選擇」lint錯誤。

我也可以把類的構造函數:

public class RequestHelper<T> extends AsyncTask<String, Response, T> { 

    .... 
    public RequestHelper(Class<Class<T>> tClass){ 
     this.tClass = tclass; 
    } 

    @Override 
    protected T doInBackground(String... strings) { 
     ... 
     Response <T> r = objectMapper.readValue(result, tclass); 
     return r.getResponse(); 
    } 
} 

// where the init of the class would have been: 

new RequestHelper<User>(Response<User>.class); 
+3

[Type erasure](http://docs.oracle.com/javase/tutorial/java/generics/erasure.html) - 在運行時無法獲取有關泛型類型參數的信息,因爲它不會編譯後不存在。明確傳入一個類是一個常用的解決方法。 – khelwood 2014-09-26 19:29:20

+0

Jackson爲此提供了類型標記。 – 2014-09-26 19:52:24

+0

我認爲你不能在一個類中捕獲泛型參數,但是你可以在一個子類中捕獲泛型參數。我認爲這可能是@SotiriosDelimanolis所指的。 – Jason 2014-09-26 20:26:26

回答

5

由於意見建議,有沒有這樣的事情

Class<GenericType<GenericArgument>> 

或者更確切地說,它不會做什麼你可能認爲它的確如此。每種類型聲明(類,接口,枚舉,原語)都會獲得一個Class實例,無論它是否是通用的。因此,即使您有類型爲Class<GenericType<ArgumentOne>>的引用和另一種類型爲Class<GenericType<ArgumentTwo>>的引用,它們所引用的實例也將完全相同。更重要的是,絕對沒有辦法查詢類型參數類型。

你似乎在使用傑克遜的ObjectMapper。它提供了一種hack以類型標記的形式獲取泛型類型信息。您可以使用TypeReferenceJavaType實例來表示泛型類型。例子here和互聯網上的其他地方。

+0

謝謝Sotiri。特別是對於上述,我使用'new TypeReference >(){}'作爲設置和提供類型的類參數。 – Diolor 2014-09-28 02:15:34

+0

@Diolor用'T'作爲類型參數時小心,你沒有提供任何具體的類型。傑克遜仍將使用其默認設置。這個_hack_只適用於具體類型,而不是類型變量。 – 2014-09-28 02:32:15

+1

呃...是的。上述「T」工作的唯一方法是在變量中傳遞一個常數類型,例如, '@JsonDeserialize(as = User.class)private T response;'這與'new TypeReference >(){}'是一樣的。死路。 – Diolor 2014-09-28 02:45:46