型変換・キャスト・数値昇格のコードトレース

集計値の平均、byteのカウンター、文字の数値を題材に、式の型と計算順序を追います。各断片は正しいmain内で一つずつ試し、コンパイル失敗と実行結果を混ぜずに記録します。

この単元で学ぶこと

  • 拡大変換と縮小変換を区別できる
  • 算術演算での数値昇格と代入可否を判断できる
  • キャスト位置による計算結果の違いを予測できる

本文解説

集計の平均を予測 int sum=9, count=2; double average=sum/count;は4.0です。格納先をdoubleにしても右辺の整数除算を先に行います。必要な4.5を得るには(double)sum/countなど、除算前に一方を浮動小数点へ変えます。

括弧の内側が先 double x=(double)(9/2);は4.0、double y=(double)9/2;は4.5です。キャスト記号が見えたら、とにかく小数が保持されると考えず、どの部分式へ適用されているかを確かめます。

byteカウンターの境界 byte count=126; count+=1;なら127、もう一度count+=1なら-128です。コンパイル時の型チェックは通りますが、表現範囲を超えたことで値が折り返します。人数や在庫など負になってはいけない値は、型の選択と入力・加算の範囲確認も設計します。

通常の代入へ書き換える byte count=126; count=count+1;はintの結果をbyteへ代入するためコンパイルエラーです。count=(byte)(count+1);なら明示した変換によりコンパイルできますが、範囲を超えた結果の折返しは残ります。キャストは範囲検証そのものではありません。

整数を縮める int value=258; byte small=(byte)value;は2です。258の下位8ビットが2だからです。(byte)-129は127になります。符号が変わることもあり、「大きな値を小さな型にすると例外で守ってくれる」とは限りません。

定数と通常変数を分ける byte x=120+7;は範囲内の定数式なので127を格納できます。byte x=120+8;は範囲外の128なので不可です。int base=120; byte x=base+7;も通常変数を含むintの式なので不可です。final int base=120;なら定数変数の条件を満たし、base+7を格納できます。

longへ変えるタイミング int n=2_000_000_000; long result=n+1_000_000_000;は、intの加算で先に桁あふれしてからlongになります。long result=(long)n+1_000_000_000;またはlongのリテラルを使うと、加算自体をlongで行えます。演算の型は代入先だけでは決まりません。

検証の手順 表示する例ではSystem.out.printlnを使い、mainの中の断片だけを交換してjavacとjavaを実行します。失敗例ではコンパイルが非0で終わること、成功例では期待値が出ることを別々に確かめます。修正後は必ず再コンパイルし、古いclassの出力を見て成功と判断しません。

図解

桁あふれの前に型を広げる
代入先をlongにするだけでは、途中のint演算をlongへ変えられない。

重要ポイント

  • 代入先だけでなく式の型を先に判断する。
  • byte/short/charの算術演算はintへ昇格することが多い。
  • キャストは情報を失う場合がある。
  • 整数除算の後でdoubleへ変えても小数は復元しない。

間違えやすい点

  • 拡大変換は精度を絶対失わないと思わない。
  • 通常変数とコンパイル時定数を同じ扱いにしない。
  • +=と通常の加算代入の変換規則を混同しない。

用語解説

拡大変換
intからlongなど、言語仕様が拡大として定める基本型間の変換。
縮小変換
longからintなど、範囲や精度を失い得る基本型間の変換。
キャスト
丸括弧で変換先の型を明示する記法。
数値昇格
演算のために数値のオペランドを共通の型等へ変換する規則。
定数式
コンパイル時に値を決められる条件を満たした式。

関連教材

参考資料

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

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