簡體   English   中英

? 超級字符串下界Java

[英]? 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類型或它的子類型(例如StringStringBuilder )。

使用該聲明,很明顯您不能將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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM