類型推斷
類型推斷是Java編譯器查看每個方法調用和相應聲明的能力,以確定使調用適用的類型參數,推理算法確定參數的類型,如果可用,還確定分配或返回結果的類型,最后,推理算法嘗試查找適用于所有參數的最具體類型。
為了說明最后一點,在下面的示例中,推斷確定傳遞給pick方法的第二個參數是Serializable類型:
static類型推斷和泛型方法T pick(T a1, T a2) { return a2; } Serializable s = pick("d", new ArrayList ());
泛型方法向你介紹了類型推斷,它使你能夠像普通方法一樣調用泛型方法,而無需在尖括號之間指定類型,考慮以下示例BoxDemo,它需要Box類:
public class BoxDemo { public static void addBox(U u, java.util.List> boxes) { Box box = new Box<>(); box.set(u); boxes.add(box); } public static void outputBoxes(java.util.List > boxes) { int counter = 0; for (Box box: boxes) { U boxContents = box.get(); System.out.println("Box #" + counter + " contains [" + boxContents.toString() + "]"); counter++; } } public static void main(String[] args) { java.util.ArrayList > listOfIntegerBoxes = new java.util.ArrayList<>(); BoxDemo. addBox(Integer.valueOf(10), listOfIntegerBoxes); BoxDemo.addBox(Integer.valueOf(20), listOfIntegerBoxes); BoxDemo.addBox(Integer.valueOf(30), listOfIntegerBoxes); BoxDemo.outputBoxes(listOfIntegerBoxes); } }
以下是此示例的輸出:
Box #0 contains [10] Box #1 contains [20] Box #2 contains [30]
泛型方法addBox定義了一個名為U的類型參數,通常,Java編譯器可以推斷泛型方法調用的類型參數,因此,在大多數情況下,你不必指定它們,例如,要調用泛型方法addBox,可以使用類型見證指定類型參數,如下所示:
BoxDemo.addBox(Integer.valueOf(10), listOfIntegerBoxes);
或者,如果省略類型見證,Java編譯器會自動推斷(從方法的參數)類型參數是Integer:
BoxDemo.addBox(Integer.valueOf(20), listOfIntegerBoxes);類型推斷和泛型類的實例化
只要編譯器可以從上下文中推斷出類型參數,就可以用一組空的類型參數(<>)替換調用泛型類的構造函數所需的類型參數,這對尖括號被非正式地稱為菱形。
例如,請考慮以下變量聲明:
Map> myMap = new HashMap >();
你可以使用一組空的類型參數(<>)替換構造函數的參數化類型:
Map> myMap = new HashMap<>();
請注意,要在泛型類實例化期間利用類型推斷,必須使用菱形,在以下示例中,編譯器生成未經檢查的轉換警告,因為HashMap()構造函數引用HashMap原始類型,而不是Map
Map類型推斷和泛型與非泛型類的泛型構造函數> myMap = new HashMap(); // unchecked conversion warning
請注意,構造函數在泛型和非泛型類中都可以是泛型的(換句話說,聲明它們自己的形式類型參數),考慮以下示例:
class MyClass{ MyClass(T t) { // ... } }
考慮以下MyClass類的實例化:
new MyClass("")
此語句創建參數化類型MyClass
Java SE 7之前版本的編譯器能夠推斷泛型構造函數的實際類型參數,類似于泛型方法,但是,如果使用菱形(<>),Java SE 7及更高版本中的編譯器可以推斷出要實例化的泛型類的實際類型參數,考慮以下示例:
MyClassmyObject = new MyClass<>("");
在此示例中,編譯器為泛型類MyClass
值得注意的是,推理算法僅使用調用參數、目標類型以及可能明顯的預期返回類型來推斷類型,推理算法不使用程序后面的結果。目標類型
Java編譯器利用目標類型來推斷泛型方法調用的類型參數,表達式的目標類型是Java編譯器所期望的數據類型,具體取決于表達式的顯示位置,考慮方法Collections.emptyList,聲明如下:
staticList emptyList();
考慮以下賦值語句:
ListlistOne = Collections.emptyList();
此語句期望List
ListlistOne = Collections. emptyList();
但是,在這種情況下,這不是必需的,不過,在其他情況下這是必要的,考慮以下方法:
void processStringList(ListstringList) { // process stringList }
假設你要使用空列表調用方法processStringList,在Java SE 7中,以下語句不編譯:
processStringList(Collections.emptyList());
Java SE 7編譯器生成類似于以下內容的錯誤消息:
List
編譯器需要類型參數T的值,因此它以值Object開始,因此,Collections.emptyList的調用返回List類型的值,該值與方法processStringList不兼容,因此,在Java SE 7中,你必須指定類型參數值的值,如下所示:
processStringList(Collections.emptyList());
Java SE 8中不再需要這樣做,什么是目標類型的概念已經擴展為包括方法參數,例如方法processStringList的參數,在這種情況下,processStringList需要一個List
processStringList(Collections.emptyList());
有關詳細信息,請參閱Lambda表達式中的目標類型。
上一篇:泛型、繼承和子類型 下一篇:泛型通配符文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/72919.html
泛型類型 泛型類型是通過類型參數化的泛型類或接口,修改以下Box類以演示此概念。 一個簡單的Box類 首先檢查一個對任何類型的對象進行操作的非泛型Box類,它只需要提供兩個方法:set,它將一個對象添加到box中,get,它將檢索它: public class Box { private Object object; public void set(Object object) ...
摘要:就等于局部變量類型推斷使用示例既然叫局部變量類型推斷,以只能用在局部變量中,下面給出更多使用示例。,本次局部變量類型推斷實戰文章就到這里了,后續帶來更多的的實戰方面的文章。 現在 Java 9 被遺棄了直接升級到了 Java 10,之前也發過 Java 10 新特性的文章,現在是開始實戰 Java 10 的時候了。 今天要實戰的是 Java 10 中最重要的特性:局部變量類型推斷,大家...
泛型通配符捕獲和Helper方法 在某些情況下,編譯器會推斷出通配符的類型,例如,列表可以定義為List,但是在評估表達式時,編譯器會從代碼中推斷出特定類型,此場景稱為通配符捕獲。 在大多數情況下,你不必擔心通配符捕獲,除非你看到包含短語capture of的錯誤消息。 WildcardError示例在編譯時產生捕獲錯誤: import java.util.List; public class ...
泛型方法 泛型方法是引入其自己的類型參數的方法,這類似于聲明泛型類型,但類型參數的范圍僅限于聲明它的方法,允許使用靜態和非靜態泛型方法,以及泛型類構造函數。 泛型方法的語法包括類型參數列表,在尖括號內,它出現在方法的返回類型之前,對于靜態泛型方法,類型參數部分必須出現在方法的返回類型之前。 Util類包含一個泛型方法compare,它比較兩個Pair對象: public class Util { ...
摘要:原文鏈接已于成功發布,不過目前絕大多數人在生產環境仍舊使用的是。這篇以案例為主的教程涵蓋了從到的絕大多數重要的語法與特性。當編譯器不能正確識別出變量的數值類型時,將不被允許使用。同步請求將會阻塞當前的線程,直到返回響應消息。 showImg(https://segmentfault.com/img/remote/1460000016575203); 原文鏈接:https://wangw...
閱讀 2315·2021-11-24 09:39
閱讀 3043·2021-10-15 09:39
閱讀 3097·2021-07-26 23:38
閱讀 2293·2019-08-30 11:14
閱讀 3417·2019-08-29 16:39
閱讀 1718·2019-08-29 15:23
閱讀 785·2019-08-29 13:01
閱讀 2670·2019-08-29 12:29