型変換とキャストのコードトレース
集計値の平均、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の出力を見て成功と判断しません。
図解
重要ポイント
- 代入先だけでなく式の型を先に判断する。
- byte/short/charの算術演算はintへ昇格することが多い。
- キャストは情報を失う場合がある。
- 整数除算の後でdoubleへ変えても小数は復元しない。
間違えやすい点
- 拡大変換は精度を絶対失わないと思わない。
- 通常変数とコンパイル時定数を同じ扱いにしない。
- +=と通常の加算代入の変換規則を混同しない。
用語解説
- 拡大変換
- intからlongなど、言語仕様が拡大として定める基本型間の変換。
- 縮小変換
- longからintなど、範囲や精度を失い得る基本型間の変換。
- キャスト
- 丸括弧で変換先の型を明示する記法。
- 数値昇格
- 演算のために数値のオペランドを共通の型等へ変換する規則。
- 定数式
- コンパイル時に値を決められる条件を満たした式。
関連教材
参考資料
教材データに登録された参考リンクです。リンク先の内容や更新日は提供元でご確認ください。
確認問題の出題・採点や学習履歴の保存にはログインが必要です。