三項演算子を理解する

条件演算子 ? : は、条件に応じて二つの式の一方から値を選びます。選んだ枝だけを実行する規則と、両方の枝から式の型を決める規則を分け、数値変換やnullの取り出しを追います。

この単元で学ぶこと

  • 条件・true側・false側を区別する
  • 選ばれた枝の副作用だけを追う
  • 数値型とラッパーの組合せで式の型を求める

本文解説

値を選ぶ演算子 int age=20;String label=age>=18?"adult":"child";では条件がtrueなのでadultが代入されます。?の左が条件、?と:の間がtrue側、:の右がfalse側です。if文が処理を選ぶのに対し、ここでは式の値を選ぶので代入や引数の中で使えます。

条件は真偽値 int n=1;int x=n?10:20;はコンパイルできません。n!=0?10:20のようにbooleanを得る必要があります。Booleanの条件はアンボクシングされるため、Boolean ok=null;int x=ok?10:20;は条件評価時にNullPointerExceptionになります。

評価する枝は一つ int n=0;int x=true?++n:++n;ではtrue側だけを評価し、xもnも1です。両方の値を先に計算してから選ぶのではありません。int d=0;int x=d==0?0:10/d;ならゼロ除算の枝を避けます。

値を返す式が必要 true?System.out.print("A"):System.out.print("B")は両枝がvoidで値を持たず、条件式の選択値にできません。表示を選ぶならSystem.out.print(true?"A":"B");のように先に文字列を選びます。また使わない枝の未宣言名などもコンパイル時に検査されます。

両枝で数値型を決める System.out.print(true?1:2.0);は1.0です。選んだ値は1でも、intとdoubleの枝の組合せから式全体はdoubleです。int x=true?1:2.0;はdoubleをintへ暗黙代入できず失敗します。実行される枝だけの型で判断しません。

小さい整数型には特別な規則 byte b=1;var x=true?b:2;では2がbyte範囲に収まるint定数なので式の型はbyteです。しかしint n=2;var x=true?b:n;ではnは定数式でなく通常の数値昇格によりintになります。単に数字が小さいことと、型規則上の定数式であることは違います。

ラッパーと数値が混ざる場合 Integer n=null;int x=true?n:0;はintとIntegerを組み合わせた数値条件式なので選んだnを取り出す際に例外になります。Integer x=true?n:0;としても、式の型intを決める規則が先に働くので救済されません。nullを保ちたい場合は両枝の型や変換を明示的に検討します。

入れ子と読みやすさ int n=0;String s=n>0?"plus":n<0?"minus":"zero";はn>0?"plus":(n<0?"minus":"zero")と結合します。複数の判定を短く書けますが、枝の型も追えることが大切です。条件が複雑なら括弧やif文に分け、結果と副作用を確認します。

図解

値を選ぶ処理と型を決める処理
未実行の枝も型決定に関与する。

重要ポイント

  • 条件はbooleanまたはBoolean。
  • 実行する枝は一つでも、両方の型を検査する。
  • 数値条件式の型は選択前に両枝の型等から決まる。
  • 入れ子の条件演算子は右から結合する。

間違えやすい点

  • 選ばれた値の見た目だけで式全体の型を決めない。
  • intとIntegerの組合せではnullの取り出しに注意する。
  • voidのメソッド呼出しを選択値にはできない。

用語解説

条件演算子
条件 ? true時の式 : false時の式という三つのオペランドを持つ演算子。
数値昇格
数値演算等のためにオペランドの型を規則に従って揃える変換。
定数式
コンパイル時に値が決まる所定の式。数値条件式の型決定にも影響する。

関連教材

参考資料

教材データに登録された参考リンクです。リンク先の内容や更新日は提供元でご確認ください。

確認問題の出題・採点や学習履歴の保存にはログインが必要です。