2016-08-25 40 views
0

我想學習使用泛型的第一次,一個相當複雜的方式爲返回類型最佳實踐。我也使用Jackson 2進行反序列化。什麼是使用Java泛型和工廠模式

我在我的return語句每次鑄造。有人能告訴我這是錯的嗎?如果是這樣,有什麼更好的方法來做到這一點?

下面是一個簡單的例子類,演示了這種情況:

class ResourceFactory <T extends Resource>{ 

    List<T> getResources(String path) 
    { 
     ResourcesResponse rgRes = new ObjectMapper() 
     .readValue(response.body().byteStream(), ResourcesResponse.class) 

     return (List<T>)rgRes.resources 
    } 
} 

UPDATE:
每一個評論,這裏是另一類機構是什麼樣的超簡化的例子。

class ResourceResponse { 
    List<Resource> resources 
} 

class ResourceGeneric extends Resource { 
} 

class ResourceTypeOne extends Resource { 
    public String typeOneOnlyProperty 
} 

class ResourceTypeTwo extends Resource { 
    public String typeTwoOnlyProperty 
} 
+1

您可以分享「ResourcesResponse」和「Resource」的定義嗎? –

+0

我已經添加了一些模擬。如果你想看傑克遜的註釋,我也可以嘲笑這些,但是傑克遜的反序列化沒有問題。我只是想確定在每個回報聲明中投出(列表)是否最好。 – solvingJ

+0

'ResourceResponse'應該是'ResourceResponse '。資源應該是'List '。你應該傳遞一個TypeReference >作爲參數。 –

回答

3

如果正確使用傑克遜可以支持泛型類型。以下是我的做法:

class ResourcesResponse<T extends Resource> { 
    List<T> resources; 
} 

class ResourceFactory<T extends Resource> { 
    // Either of these should work; pick your constructor 
    private JavaType responseType; 
    private TypeReference<ResourcesResponse<T>> responseType; 

    // Option A 
    // Involves some boilerplate, but keeps the constructor simple 
    // Use: new ResourceFactory<ResourceTypeOne>(ResourceTypeOne.class) 
    ResourceFactory(Class<T> resourceType) { 
     this.responseType = TypeFactory.defaultInstance() 
       .constructParametricType(ResourcesResponse.class, resourceType); 
    } 

    // Option B 
    // Cleaner internally, but exposes implementation details 
    // Use: new ResourceFactory<ResourceTypeOne>(new TypeReference<ResourcesResponse<ResourceTypeOne>>() {}) 
    ResourceFactory(TypeReference<ResourcesResponse<T>> responseType) { 
     this.responseType = responseType; 
    } 

    List<T> getResources(String path) 
    { 
     ResourcesResponse<T> rgRes = new ObjectMapper() 
     .readValue(response.body().byteStream(), responseType); 

     return rgRes.resources; 
    } 
} 
+0

感謝您的回答。仍在閱讀。你的意思是把這個變量命名爲別的:private TypeReference > responseType; – solvingJ

+0

它看起來像你的方法的主要區別在於你需要一個類名作爲參數傳入parens(),而不是通過箭頭<>傳入類型信息。我猜測這是唯一能夠告訴傑克遜究竟是什麼類反序列化爲動態的東西(只有「T」符號才能做到的事情)。這實際上對我特別有用,因爲我收到了一些JSON響應中沒有包含類型的良好指示的情況,所以我必須編寫一個選擇器並傳入一個類名。這對我有很大的幫助。 – solvingJ

+0

選擇這個作爲最佳答案,因爲它也解釋了我的場景中的傑克遜組件。很徹底!非常感謝你! – solvingJ

1

因爲類型擦除的快速失敗的技術是通過資源子類:

public <T extends Resource> List<T> getResources(Class<T> resourceType, String path) 
{ 
    ResourcesResponse rgRes = new ObjectMapper() 
    .readValue(response.body().byteStream(), ResourcesResponse.class) 

    return Collections.checkedList(rgRes.resources, resourceType); 
} 

這將確保這樣的不安全類型轉換的代碼有沒有其他類的值被添加。

這不「檢查」原始列表

rgRes.resources.forEach(res -> resourceType.cast(res)) 

而且這不是一個簡單的鑄件。

+0

我明白了你的觀點,實際上我正在努力實現JB Nizets的評論,即上行並將ResourceResponse更改爲ResourceResponse ,並將List 中的資源更改爲List 。 .....後續問題,「List 」部分從來不適用於我的方法,我似乎只能在課堂上使用。它表示它在T之後期待>,另外還有三條紅線出現。任何想法我做錯了什麼? – solvingJ

+0

實施例:這是不對的定義:公共類盒{ 公共列表檢查(T t)的{ } } – solvingJ

+0

我在仿製藥部分的錯誤,所以做:'公共列表檢查(...)' –