2018年3月にリリースされたJava 10より、varを用いた型推論によるローカル変数の宣言が可能になりました。varの登場で変数宣言時の型が省略可能になり、Javaのコードがスッキリ書けるようになりました。
この記事では、varを使って型推論を行ったローカル変数の宣言方法や、varを使用する時の注意点などについて解説していきます。
varの基本的な使い方
最初は、varを用いた変数の宣言方法を見てみましょう。
Java10以前までのJavaは、変数宣言時に次のように型を必ず指定する必要がありました。
String str = "12345";
FileOutputStream file = new FileOutputStream("path/to/file”);
varを使用すると、初期値で代入される値からデータ型を推論するため、変数宣言時の方を省略できるようになりました。
次のコードの場合、変数strはString、変数fileはFileOutputStreamとして宣言されます。
var str = "12345";
var file = new FileOutputStream("path/to/file”);
このように、varは初期値が明確な場合の変数を宣言する時に、型の指定を省略できます。
初期値がない変数にvarは使えない
先述のように、varは初期値で代入される値から型を推論するため、次のように変数宣言時に初期値を指定していない場合は使えず、次のエラーによりビルドが通りません。
var str; //cannot infer type for local variable str
varの注意点
ここまでvarの基本的な使い方を解説してきました。ここからはvarを使う上での基本的な知識や注意点について解説していきます。
varで宣言された変数は静的型付け
varで宣言された変数は、静的型付けされた変数(コンパイル時にデータ型が決まる)であるため、varで宣言した変数に、別の型の値を代入することはできません。
実際に、varで宣言した変数がどのように定義されているか確認してみましょう。
// varでString型の変数を宣言
var str = "Hello Java";
System.out.println(str.getClass()); // [出力結果] class java.lang.String
// varでArrayListを宣言
var array = new ArrayList();
System.out.println(array.getClass()); // [出力結果] class java.util.ArrayList
このようにgetClass()メソッドで変数の型を調べると、宣言時に代入した初期値で変数の型が定義され、コンパイル時点で型が決まっていることが分かります。
次のコードは、varで宣言した変数「str」の初期値にString型の値を代入し、その後の行でint型の値を再代入しようとするコードですが、このようなコードはコンパイル時にエラーになります。
// 文字列(String型)の値を代入し、Stringとして静的型付けされた変数をvarで宣言
var str = "Hello Java";
// String型の変数strにint型の値を代入
str = 12345;
▪️コンパイルエラーメッセージ
incompatible types: int cannot be converted to String
varをカンマで区切った複合宣言はできない
型を指定して宣言をする変数であれば、カンマで区切って複数の変数を宣言する方法(複合宣言)が使用できます。
// int型の変数を1行で複数宣言
int intA = 1, intB = 2;
しかしvarを使った変数宣言では、この複合宣言は使えません。(コンパイルエラーとなる)
// varを使ってint型の変数を1行で複数宣言
var intA = 1, intB = 2; // 'var' is not allowed in a compound declaration
数値はプリミティブ型として変数宣言される
varを使ってintやlongおよびcharなどの値を代入して変数を宣言すると、すべてプリミティブ型の変数として宣言されます。
var intValue = 12345; // int
var longValue = 1234567890L; // long
var doubleValue = 123.456; // double
var floatValue = 3.234F; // float
IntergerやLongなどの参照型として数値型の変数を宣言したい場合は、次のように明示的に参照方のインスタンスを指定して宣言を行います。
var intValue = Integer.valueOf(12345); // Integer
var longValue = Long.valueOf(1234567890L); // Long
var doubleValue = Double.valueOf(123.456); // Double
var floatValue = Float.valueOf(3.234F); // Float
varの使いすぎには要注意
varによる変数の宣言は、変数の型の指定を省略できるため便利ではありますが、あらゆる場面でvarを多用すると、かえってソースコードが読みにくくなることがあります。
varを使う事で、コードがスッキリして読みやすくなる例と、varを使ったため逆にコードが読みづらくなる例を見ていきましょう。
varを使うことでコードが読みやすくなる例
変数宣言時に、右辺で代入する値のインスタンスを指定して、誰が見ても変数の型が明らかである場合は、varの使用が有効です。
特にFileOutputStreamなどの長いクラスであれば、varにより左辺の型の指定が省略できるため、コードもスッキリします。
var i = 1234;
var file = new FileOutputStream("path/to/file”);
varで逆にコードが分かりづらくなる例
varで宣言した変数の初期値が、メソッドなどの戻りである場合、戻り値の型が容易に想像できず、結果的に変数の型を調べるのに、呼び出しているメソッドの宣言まで1つ1つ確認しなかればいけないため、コードの可読性が低下します。
実際のコード例を見てみましょう。
// getTime()の戻り値はlongの数値であるが、
// メソッド名だけでは、色々な型の戻り値が想定されるため、すぐに変数の型が分からない
var time = date.getTime();
// 独自に作成したクラスのメソッドを読んでいるが、
// このメソッド名だけでは、どのような戻り値かが分からないため、変数の方も想像できない
var result = myClass.updateUser();
varは、コードを組む時のタイプ量も少ないため、安易に使ってしまいがちですが、後々の保守などのことを考えてvarを使う前に、コードを後からみた時に変数の型が容易に想像可能かを一度検討してから使うようにしていきましょう。
開発プロジェクトによっては、varが使用禁止なところも
開発プロジェクトによってはvarの使用をコーディング規約という、プログラムを組む上で守るべきルールに定めているところもあります。
Javaをはじめとする多くの言語で、varのような型推論を行った変数宣言ができる言語が多くなったため、時代の流れに逆行している感じではありますが、開発プロジェクトでルールが定められている時は、それをしっかりと守りましょう。
まとめ
Java10より使えるようになったvarによる型推論について解説してきました。
varは便利な一方で、多用するとコードの可読性を悪くするため、適切な使い方で積極的に使っていきましょう。
Javaには、どんな型の値でも入るObject型があります。Objectであれば上のコードのようなStringの値を代入した後に、intの値を代入するといった事も問題なく可能ですが、varはコンパイル時に初期値で代入された値でデータ型が確定するため、それ以外の型の値を後から代入することはできません。Objectとvarを混同しないように気を付けましょう。