[解決済み] ブール演算子、条件演算子、自動ボックス化
質問
なぜ
NullPointerException
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
}
?
解決策としては
false
を
Boolean.FALSE
を避けるために
null
にアンボックスされる。
boolean
--というのはありえないことです。しかし、それは問題ではありません。問題は
なぜ
? この挙動、特に2番目のケースについて、JLSで確認した文献はありますか?
どのように解決するのですか?
違いは、明示的な型である
returnsNull()
メソッドがコンパイル時の式の静的型付けに影響することです。
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
というように、この節が適用されます。第2オペランドと第3オペランドの一方がboolean型で、もう一方の型がboolean型の場合、条件式の型はboolean型となります。
式の型は
boolean
であるため、2番目のオペランドは強制的にboolean
. コンパイラは自動アンボックスコードを第2オペランドに挿入します(返り値はreturnsNull()
の戻り値) に自動アンボックスコードを挿入し、それをboolean
. もちろん、これはnull
がランタイムに返されます。 -
E2の場合、第2オペランドと第3オペランドの型は
<special null type>
(です(ただしBoolean
のように!)、そしてboolean
のように、それぞれ、特定の型付け句は適用されません ( を読みに行く! )なので、最後の "others"節が適用されます。さもなければ、第2、第3オペランドはそれぞれS1、S2型である。S1に箱詰め変換を適用した結果の型をT1、S2に箱詰め変換を適用した結果の型をT2とする。条件式の型は、lub(T1, T2) (§15.12.2.7) に捕捉変換 (§5.1.10) を適用した結果である。
-
S1 ==
<special null type>
(参照 §4.1 ) -
S2 ==
boolean
-
T1 == box(S1)==」です。
<special null type>
(のボクシング変換のリストの最後の項目を参照してください)。 §5.1.7 ) - T2 == box(S2) == `ブール値
-
lub(T1, T2) == `ブール値
Boolean
つまり、条件式の型は
Boolean
で、3番目のオペランドは強制的にBoolean
. コンパイラは3番目のオペランドに自動ボックス化コードを挿入します (false
). 2 番目のオペランドは、次のように自動解凍を必要としません。E1
のように自動アンボックスを必要としないので、自動アンボックスのNPEは発生しません。null
が返されても自動アンボックスのNPEは発生しません。 -
S1 ==
この質問には、同じようなタイプの分析が必要です。
関連
-
この行に複数のマーカーがある - HttpServletResponseが型エラーに解決できない
-
[解決済み] JavaにおけるHashMapとHashtableの違いは何ですか?
-
[解決済み] Javaにおけるpublic、protected、package-private、privateの違いは何ですか?
-
[解決済み] serialVersionUIDとは何ですか、またなぜそれを使用する必要がありますか?
-
[解決済み] リフレクションとは何か、なぜ有用なのか?
-
[解決済み] Javaで配列を宣言し、初期化する方法は?
-
[解決済み] Kotlin 三項条件演算子
-
[解決済み] 3つのブール値のうち、少なくとも2つが真であるかどうかをチェックする
-
[解決済み】Pythonに三項条件演算子はありますか?
-
[解決済み】なぜJavaの+=, -=, *=, /=複合代入演算子はキャスティングを必要としないのですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
ファインバグタイプ
-
eclipse アクセス制限です。タイプ 'xxx' は API ではありません(必須ライブラリ '' の制限)。
-
Enumとの組み合わせでswitchの使い方を一度覚えるために必要な定数式
-
JavaMailのメール送信が失敗するケースとその説明の分析
-
プロジェクトの依存関係を解決できなかった 解決
-
JQuery DataTable 详解
-
Eclipseプロンプトを実行する java仮想マシンを使用しない
-
HttpClientがGZIP形式でない場合の対処法
-
ブラウザでの大容量ファイルスライスアップロード(Javaサーバサイド実装)
-
[解決済み】JavaのBooleanとbooleanの比較