2010-02-10 44 views
5

今天我遇到了一些我覺得可疑的代碼。這是一個簡化的例子(不現實)。在返回集合的接口中使用Java泛型。最佳實踐?陷阱?

public interface IListable { 
    //returns first n items from list 
    public ArrayList getFirstNThings(int n); 

    //returns last n items from list 
    public ArrayList getLastNThings(int n); 
} 

然後有一個執行者,像這樣:

public GroceryList implements IListable { 
    private ArrayList<GroceryItem> groceries; 

    public GroceryList() { 
     this.groceries = new ArrayList<GroceryItem>(); 
    } 

    public ArrayList<GroceryItem> getFirstNThings(int n) { 
     ArrayList<GroceryItem> firstNThings = new ArrayList<GroceryItem>(); 
     for (int i=0; i < n; i++) { 
      firstNThings.add(this.groceries.get(i)); 
     } 
     return firstNThings 
    } 

    public ArrayList<GroceryItem> getLastNThings(int n) { 
     ArrayList<GroceryItem> lastNThings = new ArrayList<GroceryItem>(); 
     for (int i=this.groceries.size(); i < this.groceries.size()-n; i--) { 
      lastNThings.add(this.groceries.get(i-1); 
     } 
     return lastNThings; 
     } 
} 

忽略任何執行上的問題,你可以在發現(我發現了一些太)。我得到的是接口沒有爲ArrayList使用任何泛型類型參數(例如ArrayList <?>),但接口方法的實現者(即ArrayList < GroceryList>)。其他的實現者可以返回任何其他類型參數的ArrayLists,否?

所以我的問題:這是一個問題嗎?我應該重構任何東西嗎?這值得麼?有什麼優勢?如果我在返回類型爲原始類型的接口中定義了一個方法,但是該方法的實際實現者返回了各種參數化類型,我可以遇到什麼樣的問題?

+2

除了sfussenegger說的,我還希望方法返回'List'而不是'ArrayList'。 – 2010-02-10 18:41:32

回答

5

如果IListable兩種方法總是返回相同的類型,使用這個代替:

public interface IListable<T> { 
    //returns first n items from list 
    public ArrayList<T> getFirstNThings(int n); 

    //returns last n items from list 
    public ArrayList<T> getLastNThings(int n); 
} 

如果這不是一個選項,請嘗試使用?代替。雖然它基本相同,但它避免了醜陋的警告。

public interface IListable { 
    //returns first n items from list 
    public ArrayList<?> getFirstNThings(int n); 

    //returns last n items from list 
    public ArrayList<?> getLastNThings(int n); 
} 

通常,在實現中使用更具體的返回類型不是超類型或接口中的問題。如果你正在處理IListable,你需要處理返回列表中的任何對象類型。如果你正在處理GroceryList,你只需要GroceryItems。這不僅適用於返回類型的genric類型參數,還適用於返回類型本身。所以如果一個接口指定了List<Foo> get(),那麼可以將它實現爲ArrayList<Foo> get()

+0

此方法還允許您將GroceryList變爲完全通用的類型列表,以供日後重用。 – Thirler 2010-02-10 18:09:28

0

最佳做法是永遠不會在你的打開代碼返回List<?>通配符,就像你不應該返回null

Java中的通配符泛型會使用您的代碼給所有編碼器帶來污染。你可以在你的關閉代碼來解決本地問題。

通常情況下,你會避免返回協方差和逆變通配符像List<? extends User>List<? super User>

你可以做到這一點,如果你知道你在做什麼,關於PECS,並且bounded wildcards讀到的一切。 不要只因爲它編譯。