varによるローカル変数型推論のコードトレース
初期化式に演算やメソッド呼出しを含めたとき、推論される型は何かを追跡します。小さな値だからbyteになる、実体が文字列だから全メソッドを呼べる、といった誤解を実行結果で解きます。
この単元で学ぶこと
- 初期化式から固定される型を求める
- varを使えない宣言を判定する
- ループ・参照・配列での型推論を追う
本文解説
式の結果を先に決める var x=5/2;では初期値の計算がintの2なのでxはintです。var x=5/2.0;ならdoubleの2.5です。var x=5/2;System.out.print(x+0.5);は2.5ですが、初期値の失われた小数部分が復元されたわけではありません。
小さい整数でも通常はint var n=1;は値がbyte範囲内でもintです。var n=(byte)1;ならキャスト式からbyteになります。ただしbyte同士の加算は通常intへ数値昇格するため、var sum=(byte)1+(byte)2;のsumはintです。値の範囲と式の型を別に記録します。
複合代入の暗黙変換 var n=(byte)127;n+=1;は複合代入に含まれるbyteへの変換で-128になります。一方n=n+1;は右辺がintなのでキャストなしではコンパイルできません。varが特殊な変換をするのではなく、推論されたbyteに通常の代入規則を適用します。
メソッドの戻り値も型情報 var a=Integer.parseInt("12");はint、var b=Integer.valueOf("12");はIntegerです。a.intValue()は呼べませんがb.intValue()は呼べます。両方をprintすると12でも、値の表示だけでは型は区別できません。
型を指定したnullと再代入 var s=(String)null;s="ok";は有効です。最初にString型が定まり、その後Stringへの代入を許します。s=null;へ戻すこともできます。var n=0;n=null;はintにnullを代入できず失敗します。初期化時と代入時の二段階で考えます。
コレクションの型引数 var a=new java.util.ArrayList<String>();なら要素はStringです。a.add(1)は許されません。var b=new java.util.ArrayList<>();ではこの初期化式に代入先からの型指定がなく、要素型Objectとなるので文字列とIntegerの両方を追加できます。varは必要な型引数まで常に推測してくれるわけではありません。
スコープは拡大しない for(var i=0;i<2;i++){}のiはfor文の外では利用できません。また同じブロックで既に宣言されたローカル変数をvarで再宣言することもできません。型名を省略する機能に、名前の重複や見える範囲を変更する効果はありません。
宣言構文と式を分ける var a[]=new int[2];は宣言側の角括弧が許されず、var a=new int[2];に直します。var f=()->1;も、そのラムダ式の対象となる関数型が決まらず不正です。必要ならjava.util.function.IntSupplier f=()->1;と型を明示します。型推論は情報不足を解消する魔法ではありません。
図解
重要ポイント
- 型は初期化式に基づきコンパイル時に決まる。
- 初期値なし・nullだけ・複数変数の同時宣言は使えない。
- 推論された型と代入される実際の値を区別する。
間違えやすい点
- varはObjectの別名でも動的型でもない。
- 配列初期化子だけではなくnewと型が必要。
- varで宣言してもfinalが自動で付くわけではない。
用語解説
- 型推論
- 式の情報からコンパイラが変数の型を決めること。
- 初期化式
- 変数宣言時に初めの値を与える式。
- 静的型
- 実行前の型検査に使う型。varでも固定される。
関連教材
参考資料
教材データに登録された参考リンクです。リンク先の内容や更新日は提供元でご確認ください。
- 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
確認問題の出題・採点や学習履歴の保存にはログインが必要です。