簡體   English   中英

Java 具有通用版本 8 和 17 的實例類型

[英]Java instance type with generic version 8 vs 17

根據 Maurice Naftalin 的 Java Generic 和 Collections,在以下選項中 -

  1. 對象實例列表
  2. obj 實例列表<?>
  3. obj 實例列表<? 擴展對象>

第一和第二是允許的,但第三不是在 java 8(版本“1.8.0_321”)中工作正常。 選項 1 和 2 編譯,選項 3 給出編譯錯誤。 但是第三個選項適用於 java 17(版本“17.0.1”2021-10-19 LTS)。 你能幫我理解為什么它在 java 17. 我正在嘗試的示例代碼 -

var a = List.of(2,3,4,5,23);
var b = a instanceof List<? extends Object>;
return b;

在 Java 16 之前, instanceof的唯一目的是檢查引用的 object 是否可分配給指定的類型,並且由於類型擦除阻止檢查 object 是否真的可分配給參數化類型,因此允許表達式偽裝是沒有意義的這樣的測試是可能的。

唯一可以測試的是 object 是否是List的實例,因此,它只允許寫… instanceof List… instanceof List<?> ,因為兩者都沒有假裝測試列表的元素類型。

從 Java 16(自 14 開始提供預覽版)開始, instanceof允許聲明指定類型的新變量。

例如:

public void someMethod(Iterable<String> i) {
    if(i instanceof List<String> l) {
        if(l.isEmpty()) return;
        // optimized List processing
    } else {
        // generic iterable processing
    }
}

這相當於

public void someMethod(Iterable<String> i) {
    if(i instanceof List<String>) {
        List<String> l = (List<String>)i;
        if(l.isEmpty()) return;
        // optimized List processing
    } else {
        // generic iterable processing
    }
}

對於新變量的聲明,僅限於原始類型或通配符類型是不切實際的。 因此,現在允許指定與隱含變量聲明和賦值相關的實際類型 arguments。 由於仍然無法檢查元素類型,因此您只能指定編譯時源類型可以在沒有未經檢查的強制轉換的情況下強制轉換為的類型。

因此,以下內容無效

Iterable<?> i = null;
boolean b = i instanceof List<String>;

因為您不能安全地從Iterable<?>轉換為List<String>

在您的示例中, var a = List.of(2,3,4,5,23); a聲明為List<Integer> ,因此, a instanceof List<? extends Object> a instanceof List<? extends Object>是有效的,因為List<Integer>可以分配給List<? extends Object> List<? extends Object> (即使沒有演員表)。

當然,指定未檢查的元素類型僅在您像第一個示例中那樣聲明變量時才有用。 但是 Java 語言遵循不添加額外規則的原則,因為某些構造比其他構造不太有用。 因此,無論您是否聲明變量,您現在始終可以按照相同的規則將實際類型 arguments 指定給instanceof

此功能稱為模式匹配,因為它被認為是 Java 所追求的更廣泛概念的特例。 在 JDK 17 中,有一個類似的switch功能可用作預覽版。

另見§14.30。 Java語言規范中的模式。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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