[英]Wild card in java Generic and <? super T> meaning, lower or upper bound
[英]? super String Lower Bound Java
我正在為作家珍妮·博亞爾斯基和斯科特·塞里科夫的OCP讀書, 書中寫着:#122
? super String
有了下限,我們就告訴Java,該列表將是String對象的列表,或者是String的超類的某些對象的列表
List<? super String> superString = new ArrayList<>();
superString.add(new String());// Valid
superString.add(new Object()); // Not Valid ? Why?. Object is a super class of String
其他例子:
List<? super IOException> exceptions = new ArrayList<Exception>();
exceptions.add(new Exception()); // Invalid, why ? Exception is a superclass of IOException
exceptions.add(new IOException());
exceptions.add(new FileNotFoundException());
我認為這句話
有了下限,我們就告訴Java,該列表將是String對象的列表,或者是String的超類的某些對象的列表
應該
將其下限告訴Java,該列表將是String對象的列表或超類是String的某些對象的列表
如果這種情況是真的,那為什么我們使用
List<? super IOException> exceptions = new ArrayList<Exception>();
代替
List<? super IOException> exceptions = new ArrayList<IOException>();
您需要了解,存在這些界限(上下限)是為了限制/指定變量的類型,而不是為了限制/指定此類集合中元素的類型。
一個例子:
List<? super String> variable = new ArrayList<CharSequence>();
使用此語句,首先創建一個ArrayList
其元素可以是CharSequence
類型或它的子類型(例如String
或StringBuilder
)。
使用該聲明,很明顯您不能將Object
添加到此列表中。 它只是不實現CharSequence
接口。 編譯器會負責。
存在用於生成泛型類型的子類型的下限和上限。 在有關PECS的問題中解釋了它們的用法。
實際上, List<? super String>
List<? super String>
是具有具體元素類型的列表,但是目前尚不知道該具體類型。 請參閱我的示例初始化。 具體類型為CharSequence
。 它只是意味着所有元素都是該具體類型(或子類型),但是在變量自己的類型中未知。
這是一個很好的解釋的鏈接<之間的區別? 超級T>和<? 在Java中擴展T>
這本書是正確的“?super String”表示該列表可能包含String或String的超類型(例如,Object,CharSequence)
在您的示例中:
List<? super String> superString = new ArrayList<>();
superString.add(new String());// 1
superString.add(new Object()); // 2
寫操作:
1-對於您可以創建的任何類型的列表均有效,因為String是一個對象,所以為CharSequence ...
List<? super String> list = new ArrayList<Object>();
list.add("String");
2-無效,因為它不能涵蓋所有情況
List<? super String> list = new ArrayList<String>();
list.add(new Object());
給定聲明的類型List<? super String>
List<? super String>
您只能添加Strings(和String子類型),小於String(supertypes)的任何內容都可能與實際的元素類型不符。
例:
這是一個例子:
interface MyInterface {
}
class MyInterfaceImpl implements MyInterface {
}
class MyInterfaceImplExtra extends MyInterfaceImpl {
}
您可能有以下情況:
List<? super MyInterfaceImpl> myList = new ArrayList<MyInterfaceImpl>();
無法編譯,因為myList變量可能指向MyInterfaceImpl或MyInterface或Object的列表。 當添加到列表中時,並不清楚您實際擁有的是哪種列表,因此僅允許您使用適用於所有情況的值。
myList.add(new MyInterface(){}); // - compile error "not applicable for the arguments"
myList.add(new MyInterfaceImpl()); // - works fine
myList.add(new MyInterfaceImplExtra()); // - works fine
一個獲取值列表的示例。 元素類型為Object,不能保證更具體的類型。 例如,在這里您期望使用Strings但得到一個List<? super String>
實際上包含對象的List<? super String>
,因此您將獲得java.lang.ClassCastException
List<String> result = (List<String>) getList();
System.out.println(result.get(0));
public static List<? super String> getList(){
List<Object> list = new ArrayList<Object>();
list.add(new Object());
return list;
}
Java 8中的用法示例:
在Stream接口中具有以下方法聲明,該聲明將謂詞類型限制為T或超類型。
Stream<T> filter(Predicate<? super T> predicate);
這樣可以確保在給定定義名稱的Person類和擴展Person並定義額外字段ID的Employee的情況下,您不能執行以下操作:
List<Person> list = new ArrayList<Person>() {{
add(new Person("John"));
add(new Person("Max"));
add(new Person("Megan"));
}};
list.stream().filter((Employee e) -> e.getId().startsWith("1")); // compile error
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.