2015-07-12 41 views
2

這聽起來有點微不足道,但我真的無法找到問題的癥結所在。是否可以超級演員名單?

List<Dog> dogs = getListOfDogs(); 
List<Cat> cats = getListOfCats(); 

feed(dogs); 
feed(cats); 

public void feed(List<Animal> animals) { 
    // feed the animal: 
    // depending on the type of animal, I might want to give it 
    // different kind of food. 
} 

class Dog implements Animal { /**/ } 
class Cat implements Animal { /**/ } 
interface Animal { /**/ } 

我的環境非常類似於上面描述的環境。 我們還假設getListOfDogsgetListOfCats是固定的,並且沒有辦法在那邊採取行動。

當然,作爲擺在那的方式,這是一個非法代碼:feed只接受List<Animal>類型,而我只能List<Cat>List<Dog>

由於feed是一種功能,幾乎相同的兩種動物,除了食物的種類(我可以通過instanceof管理它),我想避免複製它,只是改變簽名。

有什麼方法可以超級投出兩個列表?像這樣的東西(這是顯然是不正確):feed((List<Animal>) getListOfDogs());

+4

'feed'應該接受'List <?擴展動物>'。請參閱:https://docs.oracle.com/javase/tutorial/extra/generics/wildcards.html –

+2

如果你還沒有看到它,那麼圍繞泛型和集合的討論很有用https://stackoverflow.com/questions/2723397/Java的泛型是什麼 - 是 - 佩奇 – beresfordt

回答

4

可以你說過你想要的,通過聲明feed這樣的:

public void feed(List<? extends Animal> animals) 

但是,你可能不希望這樣做,因爲你的後續聲明:

由於feed是一種功能,幾乎相同的兩種動物,除了食物的種類(我可以通過instanceof管理它)...

不要輕易達到instanceof,它通常是錯誤的工具。相反,參數feed

private void feed(List<? extends Animal> animals, Food food) 

...然後

public void feed(List<Dog> animals) { 
    this.feed(animals, this.dogFood); 
} 

public void feed(List<Cat> animals) { 
    this.feed(animals, this.catFood); 
} 

...或相似。

6

什麼你要找的是:

public void feed(List<? extends Animal> animals) { 

這將接受List<Animal>,或List<Dog>,或List<Cat>,或等等。您將無法向animals添加任何內容,因爲它可以是任何類型的列表。如果您訪問animals中的項目,則會返回Animal類型的參考。

1

如果它不會讓你直接轉換爲List<Animal>,那麼你可以轉換爲List沒有泛型參數,然後List<Animal>,但這不是一個好方法。

這不是一個好的方法,因爲一旦你改變了泛型參數,你就可以將貓放入你的狗列表中。

相反,飼料函數的參數應該是不同

public void feed(List<? extends Animal> animals) { 
    // feed the animal: 
} 

這樣,你就可以從列表中爲Animal小號獲得動物,但是不能把錯誤的動物鍵入列表中。

相關問題