簡體   English   中英

Java條件運算符?:結果類型

[英]Java conditional operator ?: result type

我對條件運算符有點疑惑。 請考慮以下兩行:

Float f1 = false? 1.0f: null;
Float f2 = false? 1.0f: false? 1.0f: null;

為什么f1變為null而第二個語句拋出NullPointerException?

Langspec-3.0 para 15.25 sais:

否則,第二和第三操作數分別是S1和S2類型。 設T1是將拳擊轉換應用於S1所產生的類型,讓T2為應用到S2的裝箱轉換所產生的類型。 條件表達式的類型是將捕獲轉換(第5.1.10節)應用於lub(T1,T2)(第15.12.2.7節)的結果。

那么對於false?1.0f:null T1是Float而T2是null類型。 但是lub(T1,T2)的結果是什么? 第15.12.2.7段只是有點太多了......

順便說一句,我在Windows上使用1.6.0_18。

PS:我知道Float f2 = false? (Float) 1.0f: false? (Float) 1.0f: null; Float f2 = false? (Float) 1.0f: false? (Float) 1.0f: null; 不拋棄NPE。

區別在於編譯時表達式的靜態類型:

摘要

E1: `(false ? 1.0f : null)`
    - arg 2 '1.0f'           : type float,
    - arg 3 'null'           : type null 
    - therefore operator ?:  : type Float (see explanation below)
    - therefore autobox arg2
    - therefore autobox arg3

E2: `(false ? 1.0f : (false ? 1.0f : null))`
    - arg 2 '1.0f'                    : type float
    - arg 3 '(false ? 1.0f : null)'   : type Float (this expr is same as E1)
    - therefore, outer operator ?:    : type float (see explanation below)
    - therefore un-autobox arg3

詳細說明:

這是我通過閱讀規范並從你得到的結果向后工作的理解。 歸結為f2 內部條件的第三個操作數的類型是null類型,而f2 外部條件的第三個操作數的類型被認為是Float。

注意:重要的是要記住,類型的確定和裝箱/拆箱代碼的插入是在編譯時完成的。 裝箱/拆箱代碼的實際執行是在運行時完成的。

Float f1 = (false ? 1.0f : null);
Float f2 = (false ? 1.0f : (false ? 1.0f : null));

f1條件和f2內部條件:( false?1.0f:null)

f1條件和f2內部條件是相同的: (false?1.0f:null) f1條件和f2內部條件中的操作數類型是:

type of second operand = float
type of third operand = null type (§4.1)

§15.25中的大多數規則都已通過,最終的評估確實適用:

否則,第二和第三操作數分別是S1和S2類型。 設T1是將拳擊轉換應用於S1所產生的類型,讓T2為應用到S2的裝箱轉換所產生的類型。 條件表達式的類型是將捕獲轉換(第5.1.10節 )應用於lub(T1,T2)(第15.12.2.7節 )的結果。

S1 = float
S2 = null type
T1 = Float
T2 = null type
type of the f1 and f2 inner conditional expressions = Float

因為對於f1,賦值是Float引用變量,表達式(null)的結果被成功分配。

對於f2外條件:( 假?1.0f:[f2內條件])

對於f2外部條件,類型是:

type of second operand = float
type of third operand = Float

注意操作數類型與直接引用文本的f1 / f2內部條件(第4.1節 )相比的差異。 由於具有2個數字可轉換類型的這種差異, §15.12.2.7中的此規則適用:

  • 否則,如果第二個和第三個操作數具有可轉換的類型(第5.1.8節 )到數字類型,那么有幾種情況:...

    • 否則,二進制數字提升(第5.6.2節 )將應用於操作數類型,條件表達式的類型是第二個和第三個操作數的提升類型。 請注意,二進制數字促銷執行拆箱轉換 (第5.1.8節 )和值集轉換(第5.1.13節 )。

由於對f2內部條件(null)的結果執行了拆箱轉換,因此引發了NullPointerException。

當您嘗試將null分配給基元時,以下內容將拋出NPE

    float f1 = false ? 1.0f: null;

我認為這是在第二個聲明中引起NPE的原因。 因為第一個三元組為float返回一個float,所以它也嘗試將false轉換為float。

第一個語句不會轉換為null,因為所需的結果是Float

例如,這不會拋出NPE,因為它不再需要轉換為原始

    Float f = false? new Float(1.0f): true ? null : 1.0f;

我認為重寫代碼會使解釋更加清晰:

    float f = 1.0f;

    Float null_Float  = false?        f  : null;       // float + null  -> OK
    Float null_Float2 = false? (Float)f  : null_Float; // Float + Float -> OK
    Float npe         = false?        f  : null_Float; // float + Float -> NPE

因此NPE是我們嘗試做類似的事情時:

Float npe = false? 1.0f : (Float)null;

是或不是,這就是問題。 :)

編輯:實際上,看起來更接近似乎這個案例實際上是哈姆雷特 (三元運算符和包裹的整數類型)和貓王 (自動拆箱無效)益智游戲之間的混合。 無論如何,我只能推薦觀看視頻,這是非常有教育意義和愉快的。

看起來JVM試圖將第二個空值解包到float而不是Float ,因此NullPointerException。 自己打一次。 我的看法是第二個如果它是因為第一個的真實部分if評估為浮點數,而不是浮點數。

再考慮一下,我認為這是一種Java告訴你,你正在做一些奇怪的事情。 只是不要嵌套三元ifs你會沒事的:-)

暫無
暫無

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

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