Java 10 LocalVariable型推論

Java 10ローカル変数型推論

1. 概要

JDK 10で最も目に見える拡張機能の1つは、初期化子を使用したローカル変数の型推論です。

このチュートリアルでは、この機能の詳細と例を示します。

2. 前書き

Java 9まで、ローカル変数の型を明示的に言及し、それを初期化するために使用される初期化子と互換性があることを確認する必要がありました。

String message = "Good bye, Java 9";

Java 10では、これがローカル変数の宣言方法です。

@Test
public void whenVarInitWithString_thenGetStringTypeVar() {
    var message = "Hello, Java 10";
    assertTrue(message instanceof String);
}

messageのデータ型は提供していません。 代わりに、the message varとしてマークし、コンパイラーは右側にある初期化子のタイプからmessage のタイプを推測します。

上記の例では、message のタイプはStringになります。

Note that this feature is available only for local variables with the initializer. メンバー変数、メソッドパラメーター、戻り値の型などには使用できません。初期化子が必要です。これがないと、コンパイラーは型を推測できません。

この機能強化は、定型コードの削減に役立ちます。例えば:

Map map = new HashMap<>();

これは次のように書き換えることができます。

var idToNameMap = new HashMap();

これは、変数のタイプではなく変数名に焦点を当てるのにも役立ちます。

もう1つの注意点は、var is not a keyword –これにより、関数名または変数名としてvar sayを使用するプログラムの下位互換性が保証されます。 varは、intと同様に、予約されたタイプ名です。

最後に、no runtime overhead in using var nor does it make Java a dynamically typed language. があることに注意してください。変数のタイプはコンパイル時に引き続き推測され、後で変更することはできません。

3. varの不正使用

前述のように、var は初期化子なしでは機能しません。

var n; // error: cannot use 'var' on variable without initializer

また、nullで初期化した場合も機能しません。

var emptyList = null; // error: variable initializer is 'null'

非ローカル変数では機能しません。

public var = "hello"; // error: 'var' is not allowed here

ラムダ式には明示的なターゲットタイプが必要なため、var は使用できません。

var p = (String s) -> s.length() > 10; // error: lambda expression needs an explicit target-type

配列初期化子の場合も同様です。

var arr = { 1, 2, 3 }; // error: array initializer needs an explicit target-type

4. varを使用するためのガイドライン

var を合法的に使用できる場合もありますが、そうすることはお勧めできません。

たとえば、コードが読みにくくなる可能性がある状況では:

var result = obj.prcoess();

ここでは、varを合法的に使用していますが、process()によって返される型を理解することが難しくなり、コードが読みにくくなります。

java.netは、Style Guidelines for Local Variable Type Inference in Java に関する専用の記事で、この機能を使用する際の判断の使用方法について説明しています。

パイプラインが長いストリームでvar isを回避するのが最善の別の状況:

var x = emp.getProjects.stream()
  .findFirst()
  .map(String::length)
  .orElse(0);

var を使用すると、予期しない結果が生じる可能性もあります。

たとえば、Java 7で導入されたdiamond演算子で使用する場合:

var empList = new ArrayList<>();

empListのタイプはList<Object>ではなくArrayList<Object>になります。 ArrayList<Employee>にする場合は、明示的にする必要があります。

var empList = new ArrayList();

表示できないタイプでvar を使用すると、予期しないエラーが発生する可能性があります。

たとえば、匿名クラスインスタンスでvar を使用する場合:

@Test
public void whenVarInitWithAnonymous_thenGetAnonymousType() {
    var obj = new Object() {};
    assertFalse(obj.getClass().equals(Object.class));
}

ここで、別のObjectobjに割り当てようとすると、コンパイルエラーが発生します。

obj = new Object(); // error: Object cannot be converted to 

これは、推定されたタイプのobj Objectではないためです。

5. 結論

この記事では、新しいJava 10ローカル変数型推論機能と例を紹介しました。

いつものように、コードスニペットはover on GitHubにあります。