varによるローカル変数型推論を理解する

varは初期化式からローカル変数の型をコンパイラに決めさせる記法です。動的に型が変わる仕組みではありません。数値、配列、参照型の例から、推論される型と後から許される操作を区別します。

この単元で学ぶこと

  • 初期化式から固定される型を求める
  • varを使えない宣言を判定する
  • ループ・参照・配列での型推論を追う

本文解説

型名を省略する宣言 int n=5;は型を明示し、var n=5;は右辺の5からintを推論します。どちらもnの型はintです。var n=5;System.out.print(n+2);は7になります。varはJava 10以降のローカル変数型推論で、ここではJava 17として扱います。

型は途中で変わらない var n=5;n=8;はintへの再代入なので可能です。n=2.5;はdoubleからintへの暗黙の代入ができずコンパイルエラーです。小数を扱いたいなら最初からvar n=5.0;やdouble n=5;と宣言します。後の用途から過去の推論をやり直すことはありません。

リテラルの型が出発点 var a=5;はint、var b=5L;はlong、var c=5.0;はdouble、var d=5.0f;はfloatです。var a=5;System.out.print(a/2);は整数同士の除算で2になります。表示する段階で小数に直すのではなく、演算に参加する型が除算の方法を決めます。

初期化式が必要 var n;では型を決める情報がなく、var n=null;では有用な変数型を推論できません。いずれもコンパイルエラーです。String s=null;なら型が明示されています。var s=(String)null;でもキャストされた式の型がStringなので宣言できますが、s.length()を実行すればnull参照による例外になります。

一つの宣言には一変数 var a=1,b=2;は認められません。var a=1;var b=2;と分けます。varはこの形ではローカル変数の型に使い、通常のフィールドやメソッドの戻り値型・通常の仮引数型の代わりにはできません。ローカル変数を宣言する位置も通常の型を使う場合と同様、構文上許される位置が必要です。

配列には式を与える var a=new int[]{2,4};はint[]を推論し、a[1]は4です。var a={2,4};という配列初期化子だけの形は使えません。またvar a[]=new int[2];のように宣言側へ角括弧を付けられません。配列型も右辺のnew int[2]などから推論します。

参照型にも型検査がある var s="cat";はStringなのでs.length()が呼べます。var x=(Object)"cat";はObjectなので、x.length()は宣言された型で見つからずコンパイルエラーです。実物が文字列であることだけでは、Object型の変数を介したメソッド呼出しを許しません。

ループとfinalで使う for(var i=0;i<3;i++)のiはintで、通常のforと同じ範囲で使えます。for(var n:new int[]{2,3})では要素型intを推論します。final var limit=3;なら再代入できませんが、varだけなら再代入可能です。省略記法と変更禁止は別々の選択です。

図解

varから操作可能な型へ
値が変わることと型が変わることは別。

重要ポイント

  • 型は初期化式に基づきコンパイル時に決まる。
  • 初期値なし・nullだけ・複数変数の同時宣言は使えない。
  • 推論された型と代入される実際の値を区別する。

間違えやすい点

  • varはObjectの別名でも動的型でもない。
  • 配列初期化子だけではなくnewと型が必要。
  • varで宣言してもfinalが自動で付くわけではない。

用語解説

型推論
式の情報からコンパイラが変数の型を決めること。
初期化式
変数宣言時に初めの値を与える式。
静的型
実行前の型検査に使う型。varでも固定される。

関連教材

参考資料

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

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