4 ローカル変数の型推論

JDK 10以降では、nullでない初期化子を持つローカル変数をvar識別子で宣言できるため、読みやすいコードを記述できます。

次に、冗長で読みにくいコードの例を示します。

URL url = new URL("http://www.oracle.com/"); 
URLConnection conn = url.openConnection(); 
Reader reader = new BufferedReader(
    new InputStreamReader(conn.getInputStream()));

この例は、var識別子でローカル変数を宣言することにより、次のように書き直すことができます。変数の型はコンテキストから推論されます。

var url = new URL("http://www.oracle.com/"); 
var conn = url.openConnection(); 
var reader = new BufferedReader(
    new InputStreamReader(conn.getInputStream()));

varはキーワードではなく予約された型名であるため、変数、メソッドまたはパッケージ名としてvarを使用する既存のコードは影響を受けません。ただし、クラス名またはインタフェース名としてvarを使用するコードは影響を受けるため、クラスやインタフェースの名前を変更することが必要となります。

varは次のタイプの変数に使用できます。

  • 初期化子を伴うローカル変数宣言:

    var list = new ArrayList<String>();    // infers ArrayList<String>
    var stream = list.stream();            // infers Stream<String>
    var path = Paths.get(fileName);        // infers Path
    var bytes = Files.readAllBytes(path);  // infers bytes[]
    
  • 拡張forループのインデックス:

    List<String> myList = Arrays.asList("a", "b", "c");
    for (var element : myList) {...}  // infers String
  • 従来のforループで宣言されるインデックス変数:

    for (var counter = 0; counter < 10; counter++)  {...}   // infers int
  • try-with-resources変数:

    try (var input = 
         new FileInputStream("validation.txt")) {...}   // infers FileInputStream
    
  • 暗黙的に型指定されるラムダ式の仮パラメータの宣言: 仮パラメータが推論型のラムダ式は、暗黙的に型指定されます

    BiFunction<Integer, Integer, Integer> = (a, b) -> a + b;

    JDK 11以降では、暗黙的に型指定されるラムダ式の各仮パラメータをvar識別子で宣言できます。

    (var a, var b) -> a + b;

    その結果、暗黙的に型指定されるラムダ式の仮パラメータ宣言の構文は、ローカル変数宣言の構文と一致します。暗黙的に型指定されるラムダ式の各仮パラメータにvar識別子を適用する場合、その結果はvarをまったく使用しない場合と同じになります。

    推論される仮パラメータとvarで宣言される仮パラメータを暗黙的に型指定されるラムダ式内で混在させたり、varで宣言される仮パラメータとマニフェスト型を明示的に型指定されるラムダ式内で混在させることはできません。次の例は使用できません。

    (var x, y) -> x.process(y)      // Cannot mix var and inferred formal parameters
                                    // in implicitly typed lambda expressions
    (var x, int y) -> x.process(y)  // Cannot mix var and manifest types
                                    // in explicitly typed lambda expressions

ローカル変数の型推論のスタイル・ガイドライン

ローカル変数宣言は、冗長な情報を排除することによって、コードの可読性を向上させることができます。ただし、有用な情報が省略されて、コードがわかりにくくなる可能性もあります。したがって、この機能はよく考えて使用してください。使用の可否に関する厳格なルールはありません。

ローカル変数宣言は単独で存在しているのではありません。周囲のコードによってvar宣言の効果が影響を受けたり、無効化される可能性があります。『Style Guidelines for Local Variable Type Inference in Java』では、周囲のコードがvar宣言に与える影響について検討し、明示的型宣言と暗黙的型宣言のトレードオフについて説明し、var宣言の効果的な使用に関するガイドラインが示されています。