java 布尔表达式_java - 布尔值,条件运算符和自动装箱
java - 布爾值,條件運算符和自動裝箱
為什么拋出false
public static void main(String[] args) throws Exception {
Boolean b = true ? returnsNull() : false; // NPE on this line.
System.out.println(b);
}
public static Boolean returnsNull() {
return null;
}
雖然這不是
public static void main(String[] args) throws Exception {
Boolean b = true ? null : false;
System.out.println(b); // null
}
?
順便提一下,該解決方案是通過2377135880046604321替換false,以避免null被拆箱至boolean - 這是不可能的。 但這不是問題。 問題是為什么? JLS中是否有任何引用證實了這種行為,尤其是第二種情況?
4個解決方案
89 votes
不同之處在于Boolean方法的顯式類型會影響編譯時表達式的靜態類型:
E1: `true ? returnsNull() : false` - boolean (auto-unboxing 2nd operand to boolean)
E2: `true ? null : false` - Boolean (autoboxing of 3rd operand to Boolean)
請參閱Java語言規范,第15.25節“條件運算符”?:
對于E1,第2和第3個操作數的類型分別為Boolean和Boolean,因此本節適用于:
如果第二個和第三個操作數之一是boolean類型,另一個類型是Boolean類型,那么條件表達式的類型是boolean。
由于表達式的類型是Boolean,因此必須將第二個操作數強制轉換為Boolean.編譯器將自動取消裝箱代碼插入第二個操作數(返回值false),使其類型為E1.這當然會導致來自null的NPE 在運行時返回。
對于E2,第2和第3個操作數的類型分別為Boolean(不是像E1中的Boolean)和false,因此不適用特定的輸入條款(請閱讀'em!),因此最終的“其他”條款適用:
否則,第二和第三操作數分別是S1和S2類型。 設T1是將拳擊轉換應用于S1所產生的類型,讓T2為應用到S2的裝箱轉換所產生的類型。 條件表達式的類型是將捕獲轉換(第5.1.10節)應用于lub(T1,T2)(第15.12.2.7節)的結果。
S1 == Boolean(見§4.1)
S2 == Boolean
T1 == box(S1)== Boolean(參見§5.1.7中的拳擊轉換列表中的最后一項)
T2 ==方框(S2)==`布爾值
lub(T1,T2)== Boolean
因此條件表達式的類型為Boolean,第3個操作數必須強制轉換為Boolean.編譯器為第3個操作數(false)插入自動裝箱代碼。 第二個操作數不需要E1中的自動拆箱,因此返回null時不會自動取消裝箱NPE。
這個問題需要類似的類型分析:
Java條件運算符?:結果類型
Bert F answered 2019-06-04T05:30:03Z
22 votes
這條線:
Boolean b = true ? returnsNull() : false;
內部轉變為:
Boolean b = true ? returnsNull().getBoolean() : false;
執行拆箱; 因此:null.getBoolean()將產生NPE
這是使用自動裝箱時的主要缺陷之一。 這種行為確實記錄在5.1.8 JLS中
編輯:我認為拆箱是由于第三個運算符是布爾類型,如(隱式強制轉換):
Boolean b = (Boolean) true ? true : false;
jjungnickel answered 2019-06-04T05:30:59Z
16 votes
從Java語言規范,第15.25節:
如果是第二個和第三個之一?? 操作數的類型為boolean和?? 另一種類型是布爾型,?? 那么條件的類型?? 表達式是布爾值。
因此,第一個示例嘗試調用Boolean.booleanValue(),以便根據第一個規則將Boolean轉換為boolean。
在第二種情況下,第一個操作數是null類型,當第二個操作數不是引用類型時,應用自動裝箱轉換:
否則,第二和第三?? 操作數是S1和S2類型?? 分別。 設T1是那種類型?? 應用拳擊的結果?? 轉換為S1,讓T2成為?? 應用拳擊造成的類型?? 轉換為S2。 的類型?? 條件表達式就是結果?? 應用捕獲轉換?? (§5.1.10)至lub(T1,T2)(§15.12.2.7)。
axtavt answered 2019-06-04T05:31:59Z
0 votes
我們可以從字節代碼中看到這個問題。 在main的字節碼的第3行,3: invokevirtual #3 // Method java/lang/Boolean.booleanValue:()Z,值為null的裝箱布爾值,invokevirtual方法java.lang.Boolean.booleanValue,它當然會拋出NPE。
public static void main(java.lang.String[]) throws java.lang.Exception;
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=2, args_size=1
0: invokestatic #2 // Method returnsNull:()Ljava/lang/Boolean;
3: invokevirtual #3 // Method java/lang/Boolean.booleanValue:()Z
6: invokestatic #4 // Method java/lang/Boolean.valueOf:(Z)Ljava/lang/Boolean;
9: astore_1
10: getstatic #5 // Field java/lang/System.out:Ljava/io/PrintStream;
13: aload_1
14: invokevirtual #6 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
17: return
LineNumberTable:
line 3: 0
line 4: 10
line 5: 17
Exceptions:
throws java.lang.Exception
public static java.lang.Boolean returnsNull();
descriptor: ()Ljava/lang/Boolean;
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=1, locals=0, args_size=0
0: aconst_null
1: areturn
LineNumberTable:
line 8: 0
Yanhui Zhou answered 2019-06-04T05:32:31Z
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的java 布尔表达式_java - 布尔值,条件运算符和自动装箱的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Linux下如何定位Java进程CPU利
- 下一篇: java annotation应用_ja