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