<? extends T>生成只讀集合
<? super T>生成只寫集合
我以某種方式明白為什么要使用只讀集合,例如在多執行緒環境中使用它(任何其他情況?)
但是為什么要使用只寫集合呢?如果您無法從中讀取并在某些時候使用它的值,那有什么意義呢?我知道你可以從中得到一個物件,但這違反了型別安全。
編輯:@Thomas 鏈接的問題(Java 中 <? super T> 和 <? extends T> 之間的區別)確實展示了如何制作只寫集合,但沒有回答“為什么”你首先需要一個。所以它不是重復的
uj5u.com熱心網友回復:
像這樣的陳述
<? extends T>生成只讀集合
<? super T>生成只寫集合
錯了。通配符元素型別沒有說明讀取或寫入的能力。
顯示反例:
static <T> void modify(List<? extends T> l) {
l.sort(Comparator.comparing(Object::toString));
l.remove(l.size() - 1);
Collections.swap(l, 0, l.size() - 1);
l.add(null);
duplicateFirst(l);
}
static <U> void duplicateFirst(List<U> l) {
U u = l.get(0);
l.add(u);
}
顯示了相當多的修改可能List<? extends T>,沒有問題。
同樣,您可以閱讀List<? super T>.
static <T> void read(List<? super T> l) {
for(var t: l) System.out.println(t);
}
由 施加的使用限制? extends T或? super T僅與T. 您不能將型別的物件(T例如從另一個方法引數中)添加到 aList<? extends T>中,因為串列的實際型別可能是 的子型別T。同樣,您不能假設 a 的元素是List<? super T>type T,因為串列的實際型別可能是 的超型別T,所以您可以做出的唯一假設是元素是 的實體Object,就像每個物件一樣。
因此,當您有類似的方法時
public static <T> void copy(List<? super T> dest, List<? extends T> src)
該方法不能從中獲取元素dest并將它們添加到src(以型別安全的方式),但只能反過來。
需要強調的是,與其他編程語言不同,Java 有使用站點變數,所以上面描述的兩個串列之間的關系只適用于copy宣告這種關系的方法。傳遞給此方法的串列不必在其整個生命周期中都是“消費者T”和“生產者”。T
所以你可以使用類似的方法
List<Integer> first = List.of(0, 1, 2, 3, 7, 8, 9);
List<Number> second = new ArrayList<>(Collections.nCopies(7, null));
Collections.copy(second, first);
List<Object> third = new ArrayList<>(Collections.nCopies(11, " x "));
Collections.copy(third.subList(2, 9), second);
System.out.println(third);
是的,copy是一個現實生活中的例子。在線演示
請注意second串列如何將其角色從兩次呼叫的使用者更改Integer為生產者,而其實際元素型別為。ObjectcopyNumber
其他示例? super T
Collections.fill(List<? super T> list, T obj)Collections.addAll(Collection<? super T> c, T... elements)
總而言之,在 Java 中,像PECS這樣的規則與方法的宣告相關,以確定方法本身中引數的(典型)角色。這提高了呼叫者的靈活性,因為它允許組合不同的不變型別,例如從 a 復制到 a 的List<Integer>示例List<Number>。
但永遠不要假設泛型型別能說明讀取或寫入集合的能力。
uj5u.com熱心網友回復:
請注意,“只寫集合”取決于觀點。
讓我們撰寫一個將一堆數字添加到集合中的方法:
public static void addNumbers(List<? super Integer> target, int count) {
for (int i = 0; i < count; i ) {
target.add(i);
}
}
對于此方法,串列target是只寫串列:該方法只能向其添加數字,它不能使用它添加到串列中的值。
另一邊是來電者:
public static void caller() {
List<Number> myList = new ArrayList<>();
addNumbers(myList, 10);
double sum = 0;
for (Number n: myList) {
sum = n.doubleValue();
}
System.out.println(sum);
}
此方法適用于特定串列 ( myList),因此可以讀取addNumbers填充到其中的值。
對于此方法,串列不是只寫串列,對于此方法,它是普通串列。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/510444.html
標籤:爪哇仿制药收藏品
