三項演算子のコードトレース
条件演算子の枝に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時の式という三つのオペランドを持つ演算子。
- 数値昇格
- 数値演算等のためにオペランドの型を規則に従って揃える変換。
- 定数式
- コンパイル時に値が決まる所定の式。数値条件式の型決定にも影響する。
関連教材
参考資料
教材データに登録された参考リンクです。リンク先の内容や更新日は提供元でご確認ください。
- https://www.oracle.com/jp/education/certification/javase-17-programmer-1/
- https://docs.oracle.com/javase/specs/jls/se17/html/jls-14.html#jls-14.4
- https://docs.oracle.com/javase/specs/jls/se17/html/jls-5.html#jls-5.1.8
- https://docs.oracle.com/javase/specs/jls/se17/html/jls-15.html#jls-15.23
- https://docs.oracle.com/javase/specs/jls/se17/html/jls-15.html#jls-15.25
- https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Integer.html
- https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Objects.html
- https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/ArrayList.html
確認問題の出題・採点や学習履歴の保存にはログインが必要です。