我知道你使用 <? 當您僅從集合中獲取值時, extends> 通配符。
假設有 Animal 超類和 Dog 和 Cat 子類。基本上我想要一個包含狗和貓的串列。我發現我可以執行以下操作:
List<? extends Animal> animalList;
List<Dog> dogList = getDogs();
List<Cat> catList = getCats();
animalList = Stream.concat(dogList.stream(), catList.stream()).collect(Collectors.toList())
// Do things according to its type
for (Animal animal : animalList) {
if (animal instance of Dog) {...}
if (animal instance of Cat) {...}
}
上面的代碼編譯。那么它是否違反了我正在向其寫入值的規則animalList?
uj5u.com熱心網友回復:
Stream.concat(dogList.stream(), catList.stream()).collect(Collectors.toList())
這將創建一個List<Animal>. 至關重要的是,不是List<? extends Animal>. 試試吧:
List<Animal> = ... all that ...
作業正常。
List<Animal>并不意味著其中的所有內容都是使用字面意思制作的new Animal()。您可以擁有一個List<Animal>僅包含Cat實體的。這些都是動物,沒關系。
? extends當您處理串列本身而不是其中的事物時,“重點”和所有這一切都是如此。具體原因如下:
List<Animal> x = new ArrayList<Cat>();
x.add(new Dog());
Cat z = x.get(0);
三重檢查上面的代碼,但它準確地解釋了? extends(and ? super) 存在的原因。泛型必須是不變的,否則會導致代碼損壞。上面的代碼一定不能編譯,因為它沒有意義。正如所寫,它確實不能編譯——第 1 行是不允許的。List<? extends Animal> x = new ArrayList<Cat>()您可以通過撰寫編譯好的“讓它作業” ,但現在x.add(new Dog()不會。
區別在于:
一個List<Animal>變數指向某個串列,該串列實際上是某個特定串列,<Animal>而不是 Animal 的某個子型別或超型別。它可能是 aLinkedList<Animal>或 an ArrayList<Animal>,這很好,但不是ArrayList<Cat>. 知道了這一點,當你從它“讀取”時,你會得到 Animal 物件,當你寫它時,Animal 很好。
List<? extends Animal>另一方面,變數是 Animal 的某個串列或Animal 的某個子型別。它可能是一個LinkedList<Dog>. 鑒于這個事實,當你閱讀時,Animal很好(Animal f = thatList.get(0)編譯得很好),但你不能寫任何東西。它可能是 Dogs 串列,但也可能是 Cats 串列,因此絕對沒有物件可以保存(除了,瑣碎地,字面意思是運算式null,寫成這樣:thatList.add(null)編譯。當然沒用) .
您將List<Animal>運算式分配給一個List<? extends Animal>很好的型別變數。而且沒必要;List<Animal> x = Stream.concat....本來也可以的。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/437858.html
上一篇:如何將型別限制為具有索引的型別?
