国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Java 泛型之上界下界通配符

shiyang6017 / 1882人閱讀

摘要:泛型之上界下界通配符本教程是為編寫的。這是在使用泛型編程時一個常見的誤解,也是一個需要學習的重要概念。通配符使用指南學習使用泛型編程時,更令人困惑的一個方面是確定何時使用上限有界通配符以及何時使用下限有界通配符。

Java 泛型之上界下界通配符
本Java教程是為JDK 8編寫的。本頁描述的示例和實踐沒有利用后續版本中引入的改進。
泛型,繼承和子類

如你所知,只要類型兼容,就可以將一種類型的對象分配給另一種類型的對象。例如,你可以指定一個整數一個對象,因為對象是一個整數的超類型:

Object someObject = new Object();
Integer someInteger = new Integer(10);
someObject = someInteger; // 好

在面向對象的術語中,這被稱為“是一種”關系。由于Integer 是一種Object,因此允許賦值。但是Integer也是一種Number,所以下面的代碼也是有效的:

public void someMethod(Number n){/ * ... * /}

someMethod(new Integer(10)); // 好
someMethod(new Double(10.1)); // 好

泛型也是如此。您可以執行泛型類型調用,將Number作為其類型參數傳遞,如果參數與Number兼容,則允許任何后續的add調用:

Box box = new Box ();
box.add(new Integer(10)); // 好
box.add(new Double(10.1)); // 好
現在考慮以下方法:

public void boxTest(Box  n){/ * ... * /}

它接受什么類型的論據?通過查看其簽名,您可以看到它接受一個類型為Box的參數。但是,這是什么意思?您是否可以按照您的預期傳遞BoxBox?答案是“”,因為BoxBox不是Box的子類型。

這是在使用泛型編程時一個常見的誤解,也是一個需要學習的重要概念。


Box不是Box的子類型,即使IntegerNumber的子類型。

注意:給定兩個具體類型 A 和 B(例如,NumberInteger),MyClassMyClass無關,無論 A 和 B 是否相關。MyClassMyClass 的公共父是Object。

有關如何在類型參數相關時在兩個泛型類之間創建類似子類型關系的信息,請參閱下面的通配符和子類型一節。

泛型類和子類型化

您可以通過擴展(extends)泛型類或實現(implements)泛型接口來對其進行子類型化。一個類或接口的類型參數與另一個類或接口的類型參數之間的關系由extendsimplements子句確定。

使用Collections類作為示例,ArrayList 實現 ListList 擴展Collection。所以 ArrayListList的子類型,它是Collection的子類型。只要不改變類型參數,就會在類型之間保留子類型關系。

Collection層次結構示例

顯示Collection層次結構示例的圖表:ArrayListList的子類型,二者都是Collection的子類型。

現在假設我們想要定義我們自己的列表接口PayloadList,它將可選值泛型類型參數P的與每個元素相關聯。它的聲明可能如下:

interface PayloadList extends List {
  void setPayload(int index, P val);
  ...
}

PayloadList的以下參數化是List的子類型:

PayloadList
PayloadList
PayloadList


PayloadList層次結構示例

PayLoadList層次結構的示意圖:PayloadListList的子類型,它是Collection的子類型。 在PayloadList的相同級別是PayloadList PayloadList。
通配符和子類型

如 泛型,繼承和子類一節中所述,泛型類之間或接口之間幾乎并不因它們的類型參數而相關。但是,您可以使用通配符在泛型類或接口之間創建關系。

給定以下兩個常規(非泛型)類:

    class A { /* ... */ }
    class B extends A { /* ... */ }

編寫以下代碼是合理的:

    B b = new B();
    A a = b;

此示例顯示常規類的繼承遵循此子類型規則:如果B擴展A,則類B是類A的子類型。此規則不適用于泛型類型

List lb = new ArrayList<>();
List la = lb;   //編譯時錯誤

鑒于IntegerNumber的子類型,ListList 之間的關系是什么?

公共父類是List

該圖表顯示 ListList 的公共父級是未知類型的List.

盡管IntegerNumber的子類型,但List不是List的子類型,實際上,這兩種類型不相關。ListList 的公共父是 List

上界(extends)的通配符與下界(super)通配符

為了在這些類之間創建關系以便代碼可以通過 List 的元素訪問Number的方法,請使用上界的通配符:

List intList = new ArrayList<>();
List  numList = intList;  // OK, List<?extends Integer>是 List< ? extends Number>的子類型

因為IntegerNumber的子類型,而numListNumber對象的列表,所以intList(是一個Integer對象列表)和numList之間現在存在關系。下圖顯示了使用上限和下限通配符聲明的多個 List 類之間的關系。

幾個通用List類聲明的層次結構。

圖表顯示: ListList List<?super Integer>的子類型。 ListList 的子類型,它是List 的子類型。 ListList <?super Number>List的子類型。 ListList 的子類型, 且都是List的子類型。
通配符使用指南

學習使用泛型編程時,更令人困惑的一個方面是確定何時使用上限有界通配符以及何時使用下限有界通配符。本文提供一些設計代碼時要遵循的一些準則。

為討論方便,認為變量具備兩個功能:

一個“In”變量

“in”變量向代碼提供數據。想象一下帶有兩個參數的復制方法:copy(src,dest)。該SRC參數提供的數據被復制,因此它是“in”參數。

一個“Out”變量

“out”變量保存數據以供其他地方使用。在復制示例中,copy(src,dest),dest參數接受數據,因此它是“out”參數。
當然,一些變量既用于“in”又用于“out”目的 - 這種情況也在本文中也用到了。

在決定是否使用通配符以及適合使用哪種類型的通配符時,可以使用“in”和“out”原則。以下列表提供了遵循的準則:

通配符指南:

使用extends關鍵字, 定義帶有上界通配符的“in”變量。

使用super關鍵字,使用下界通配符定義“out”變量。

在可以使用Object類中定義的方法訪問“in”變量的情況下,使用無界通配符。

在代碼需要作為“in”和“out”變量訪問變量的情況下,不要使用通配符。

這些指南不適用于方法的返回類型。應該避免使用通配符作為返回類型,因為它強制程序員使用代碼來處理通配符。

List 可以被非正式地認為是只讀的,但這不是一個嚴格的保證。假設您有以下兩個類:

class NaturalNumber {

    private int i;

    public NaturalNumber(int i) { this.i = i; }
    // ...
}

class EvenNumber extends NaturalNumber {

    public EvenNumber(int i) { super(i); }
    // ...
}

請考慮以下代碼:

List le = new ArrayList<>();
List ln = le;
ln.add(new NaturalNumber(35));  // compile-time error //編譯時錯誤

因為ListList,您可以賦值leln。但是你不能使用ln將自然數添加到偶數列表中。列表中的以下操作是可能的:

您可以添加null。

你可以調用清除。

您可以獲取迭代器并調用remove。

您可以捕獲通配符并寫入從列表中讀取的元素。

你可以看到List在嚴格意義上不是只讀的,但您可能會這樣想,因為您無法存儲新元素或更改列表中的現有元素。

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/77808.html

相關文章

  • Java? 教程(泛型配符

    泛型通配符 在泛型代碼中,稱為通配符的問號(?)表示未知類型,通配符可用于各種情況:作為參數、字段或局部變量的類型,有時作為返回類型(盡管更好的編程實踐是更加具體),通配符從不用作泛型方法調用、泛型類實例創建或超類型的類型參數。 以下部分更詳細地討論通配符,包括上界通配符、下界通配符和通配符捕獲。 上界通配符 你可以使用上界通配符來放寬對變量的限制,例如,假設你要編寫一個適用于List、List和...

    qingshanli1988 評論0 收藏0
  • Java? 教程(泛型配符使用指南)

    泛型通配符使用指南 學習使用泛型編程時更困惑的一個方面是確定何時使用上界通配符以及何時使用下界通配符,此頁面提供了設計代碼時要遵循的一些準則。 對于本文的討論,將變量看作提供的兩個功能之一是有幫助的: 一個In變量 in變量向代碼提供數據,想象一下帶有兩個參數的復制方法:copy(src, dest),src參數提供要復制的數據,因此它是in參數。 一個Out變量 out變量保存數據以供其他地方使...

    raledong 評論0 收藏0
  • Java泛型總結

    摘要:靜態變量是被泛型類的所有實例所共享的。對于這個類型系統,有如下的一些規則相同類型參數的泛型類的關系取決于泛型類自身的繼承體系結構。在代碼中避免泛型類和原始類型的混用。參考泛型類型擦除 Java泛型總結 Java泛型是JDK5引入的一個新特性,允許在定義類和接口的時候使用類型參數(type parameter)。聲明的類型參數在使用的時候使用具體的類型來替換。泛型最主要的應用是在JDK5...

    CoreDump 評論0 收藏0
  • 型之配符

    摘要:調用相當于通過使用通配符,可以傳遞任何類型的對象,但也是有缺點的。使用通配符,賦值傳值的時候方便了,但是對泛型類中參數為泛型的方法起到了副作用。結論當使用父界限定通配符時,泛型類中返回值為泛型的方法不能使用。 數組 VS List 第一回合數組類型為Object,可以存儲任意類型的對象,List集合同樣可以做到 Object[] obj = new Object[1]; List li...

    PingCAP 評論0 收藏0
  • Java泛型

    摘要:虛擬機中并沒有泛型類型對象,所有的對象都是普通類。其原因就是泛型的擦除。中數組是協變的,泛型是不可變的。在不指定泛型的情況下,泛型變量的類型為該方法中的幾種類型的同一個父類的最小級,直到。 引入泛型的主要目標有以下幾點: 類型安全 泛型的主要目標是提高 Java 程序的類型安全 編譯時期就可以檢查出因 Java 類型不正確導致的 ClassCastException 異常 符合越早出...

    woshicixide 評論0 收藏0

發表評論

0條評論

shiyang6017

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<