泛型通配符
在泛型代碼中,稱為通配符的問(wèn)號(hào)(?)表示未知類型,通配符可用于各種情況:作為參數(shù)、字段或局部變量的類型,有時(shí)作為返回類型(盡管更好的編程實(shí)踐是更加具體),通配符從不用作泛型方法調(diào)用、泛型類實(shí)例創(chuàng)建或超類型的類型參數(shù)。
以下部分更詳細(xì)地討論通配符,包括上界通配符、下界通配符和通配符捕獲。
上界通配符你可以使用上界通配符來(lái)放寬對(duì)變量的限制,例如,假設(shè)你要編寫一個(gè)適用于List
要聲明一個(gè)上界通配符,請(qǐng)使用通配符("?"),后跟extends關(guān)鍵字,后跟上界,請(qǐng)注意,在此上下文中,extends在一般意義上用于表示“extends”(如在類中)或“implements”(如在接口中)。
要編寫適用于Number和Number的子類型列表的方法,例如Integer、Double和Float,你可以指定List<?extends Number>,List
考慮以下process方法:
public static void process(List extends Foo> list) { /* ... */ }
上界通配符 extends Foo>,其中Foo是任何類型,匹配Foo和Foo的任何子類型,process方法可以像Foo類型一樣訪問(wèn)列表元素:
public static void process(List extends Foo> list) { for (Foo elem : list) { // ... } }
在foreach子句中,elem變量遍歷列表中的每個(gè)元素,現(xiàn)在可以在elem上使用Foo類中定義的任何方法。
sumOfList方法返回列表中數(shù)字的總和:
public static double sumOfList(List extends Number> list) { double s = 0.0; for (Number n : list) s += n.doubleValue(); return s; }
以下代碼使用Integer對(duì)象列表打印sum = 6.0:
Listli = Arrays.asList(1, 2, 3); System.out.println("sum = " + sumOfList(li));
Double值列表可以使用相同的sumOfList方法,以下代碼打印sum = 7.0:
List無(wú)界通配符ld = Arrays.asList(1.2, 2.3, 3.5); System.out.println("sum = " + sumOfList(ld));
使用通配符(?)指定無(wú)界通配符類型,例如List>,這稱為未知類型的列表,有兩種情況,無(wú)界通配符是一種有用的方法:
如果你正在編寫可以使用Object類中提供的功能實(shí)現(xiàn)的方法。
當(dāng)代碼使用泛型類中不依賴于類型參數(shù)的方法時(shí),例如,List.size或List.clear,事實(shí)上,經(jīng)常使用Class>,因?yàn)?b>Class
考慮以下方法,printList:
public static void printList(List
printList的目標(biāo)是打印任何類型的列表,但它無(wú)法實(shí)現(xiàn)該目標(biāo) — 它只打印一個(gè)Object實(shí)例列表,它不能打印List
public static void printList(List> list) { for (Object elem: list) System.out.print(elem + " "); System.out.println(); }
因?yàn)閷?duì)于任何具體類型A,List是List>的子類型,你可以使用printList打印任何類型的列表:
Listli = Arrays.asList(1, 2, 3); List ls = Arrays.asList("one", "two", "three"); printList(li); printList(ls);
在本課程的示例中使用了Arrays.asList方法,此靜態(tài)工廠方法轉(zhuǎn)換指定的數(shù)組并返回固定大小的列表。
重要的是要注意List和List>是不一樣的,你可以將Object或Object的任何子類型插入List,但是你只能在List>中插入null,通配符使用指南部分提供了有關(guān)如何確定在給定情況下應(yīng)使用哪種通配符(如果有)的更多信息。
下界通配符上界通配符部分顯示上界通配符將未知類型限制為該類型的特定類型或子類型,并使用extends關(guān)鍵字表示,以類似的方式,下界通配符將未知類型限制為該類型的特定類型或超類型。
使用通配符(?)表示下界通配符,后跟super關(guān)鍵字,后跟下界: super A>。
你可以指定通配符的上界,也可以指定下界限,但不能同時(shí)指定兩者。
假設(shè)你要編寫一個(gè)將Integer對(duì)象放入列表的方法,為了最大限度地提高靈活性,你希望該方法可以處理List
要編寫適用于Integer和Integer超類型列表的方法,例如Integer、Number和Object,你可以指定List super Integer>,List
以下代碼將數(shù)字1到10添加到列表的末尾:
public static void addNumbers(List super Integer> list) { for (int i = 1; i <= 10; i++) { list.add(i); } }通配符和子類型
如泛型、繼承和子類型中所述,泛型類或接口不相關(guān),僅僅因?yàn)樗麄兊念愋椭g存在關(guān)系,但是,你可以使用通配符在泛型類或接口之間創(chuàng)建關(guān)系。
給定以下兩個(gè)常規(guī)(非泛型)類:
class A { /* ... */ } class B extends A { /* ... */ }
編寫以下代碼是合理的:
B b = new B(); A a = b;
此示例顯示常規(guī)類的繼承遵循此子類型規(guī)則:如果B擴(kuò)展A,則B類是A類的子類型,此規(guī)則不適用于泛型類型:
List lb = new ArrayList<>(); List la = lb; // compile-time error
假設(shè)Integer是Number的子類型,List
雖然Integer是Number的子類型,但List
為了在這些類之間創(chuàng)建關(guān)系以便代碼可以通過(guò)List
List extends Integer> intList = new ArrayList<>(); List extends Number> numList = intList; // OK. List extends Integer> is a subtype of List extends Number>
因?yàn)?b>Integer是Number的子類型,而numList是Number對(duì)象的列表,所以intList(Integer對(duì)象列表)和numList之間現(xiàn)在存在關(guān)系,下圖顯示了使用上界和下界通配符聲明的多個(gè)List類之間的關(guān)系。
上一篇:類型推斷 下一篇:泛型通配符捕獲和Helper方法文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/72943.html
Java? 教程 Java教程是為JDK 8編寫的,本頁(yè)面中描述的示例和實(shí)踐沒(méi)有利用在后續(xù)版本中引入的改進(jìn)。 Java教程是希望使用Java編程語(yǔ)言創(chuàng)建應(yīng)用程序的程序員的實(shí)用指南,其中包括數(shù)百個(gè)完整的工作示例和數(shù)十個(gè)課程,相關(guān)課程組被組織成教程。 覆蓋基礎(chǔ)知識(shí)的路徑 這些教程以書籍的形式提供,如Java教程,第六版,前往Amazon.com購(gòu)買。 入門 介紹Java技術(shù)和安裝Java開發(fā)軟件并使用...
泛型通配符捕獲和Helper方法 在某些情況下,編譯器會(huì)推斷出通配符的類型,例如,列表可以定義為L(zhǎng)ist,但是在評(píng)估表達(dá)式時(shí),編譯器會(huì)從代碼中推斷出特定類型,此場(chǎng)景稱為通配符捕獲。 在大多數(shù)情況下,你不必?fù)?dān)心通配符捕獲,除非你看到包含短語(yǔ)capture of的錯(cuò)誤消息。 WildcardError示例在編譯時(shí)產(chǎn)生捕獲錯(cuò)誤: import java.util.List; public class ...
泛型通配符使用指南 學(xué)習(xí)使用泛型編程時(shí)更困惑的一個(gè)方面是確定何時(shí)使用上界通配符以及何時(shí)使用下界通配符,此頁(yè)面提供了設(shè)計(jì)代碼時(shí)要遵循的一些準(zhǔn)則。 對(duì)于本文的討論,將變量看作提供的兩個(gè)功能之一是有幫助的: 一個(gè)In變量 in變量向代碼提供數(shù)據(jù),想象一下帶有兩個(gè)參數(shù)的復(fù)制方法:copy(src, dest),src參數(shù)提供要復(fù)制的數(shù)據(jù),因此它是in參數(shù)。 一個(gè)Out變量 out變量保存數(shù)據(jù)以供其他地方使...
泛型的限制 要有效地使用Java泛型,必須考慮以下限制: 無(wú)法使用基元類型實(shí)例化泛型類型 無(wú)法創(chuàng)建類型參數(shù)的實(shí)例 無(wú)法聲明類型為類型參數(shù)的靜態(tài)字段 無(wú)法對(duì)參數(shù)化類型使用強(qiáng)制類型轉(zhuǎn)換或instanceof 無(wú)法創(chuàng)建參數(shù)化類型的數(shù)組 無(wú)法創(chuàng)建、捕獲或拋出參數(shù)化類型的對(duì)象 無(wú)法重載將每個(gè)重載的形式參數(shù)類型擦除為相同原始類型的方法 無(wú)法使用基元類型實(shí)例化泛型類型 考慮以下參數(shù)化類型: class P...
泛型、繼承和子類型 如你所知,只要類型兼容,就可以將一種類型的對(duì)象分配給另一種類型的對(duì)象,例如,你可以將Integer分配給Object,因?yàn)镺bject是Integer的超類型之一: Object someObject = new Object(); Integer someInteger = new Integer(10); someObject = someInteger; // OK ...
閱讀 3787·2021-11-25 09:43
閱讀 2206·2021-11-23 10:13
閱讀 838·2021-11-16 11:44
閱讀 2385·2019-08-29 17:24
閱讀 1396·2019-08-29 17:17
閱讀 3493·2019-08-29 11:30
閱讀 2597·2019-08-26 13:23
閱讀 2360·2019-08-26 12:10