三項演算子のコードトレース

条件演算子の枝にchar、ラッパー、null、代入を置いた例を比較します。条件が定数でも両枝の型検査は残ることを確認し、式の型・実行された枝・最後の値の三段階で解きます。

この単元で学ぶこと

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

本文解説

条件を数値比較で作る int n=-3;int abs=n<0?-n:n;は3になります。負かどうかを判定し、true側だけで符号を反転します。ただしint最小値の絶対値はintに収まらないため、どの値でも必ず正になると一般化しません。ここでは各例の初期値から追跡します。

条件部分の副作用も先に起きる int n=0;int x=n++==0?n:n+10;では、条件比較に古い0を使った後nは1になり、true側のnを読むのでxは1です。枝だけでなく条件式が変数を変更する場合があります。条件直後の状態を書き出してから枝に進みます。

入れ子のどの条件まで進むか int a=2,b=5;int max=a>b?a:b;は5です。さらに複数条件を入れ子にするとき、外側で選ばれなかった枝の条件も実行されません。true?7:false?8:9は7で、true?7:(false?8:9)と結合します。

charとint定数 char c='A';System.out.print(true?c:66);はAです。66はcharの範囲に収まるint定数なので結果型はcharです。65536はcharの範囲を超えるため、true?c:65536はintになり65を表示します。文字の見た目と文字コードの数値を区別します。

両方ラッパーなら参照のまま Integer n=null;Integer x=true?n:Integer.valueOf(0);は両枝がIntegerなのでnullを保持できます。true?n:0との違いはfalse側がintかIntegerかです。Booleanも両枝がBooleanならBoolean型となりnullを保持でき、一方がbooleanなら取り出しが必要になる場合があります。

代入先Numberは数値昇格を止めない Number x=true?1:2.0;では数値条件式はdoubleとなり、その後Doubleにボックス化してNumberへ代入します。x.getClass().getSimpleName()はDoubleです。NumberがIntegerも保持できることから、選んだ1が必ずIntegerになると考えないようにします。

小整数型と定数性 byte b=2;final int k=3;var x=false?b:k;ではkは定数式でbyte範囲に収まり、式はbyteです。finalのないint変数なら値が3でも通常intへ昇格します。finalでも値がコンパイル時に決まらない初期化式なら、同じ定数式の特別規則が使えるとは限りません。

参照の選択と使う側の型 Object x=true?"abc":new StringBuilder("d");はObjectへの代入として可能で、x.toString()なら呼べます。しかしx.length()はObjectに宣言がないためコンパイルできません。条件演算子で参照を選んだ後も、使う変数の静的型によるメンバー検査が続きます。

図解

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

重要ポイント

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

間違えやすい点

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

用語解説

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

関連教材

参考資料

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

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