JEP 286 から、JDK 10(18.3)でローカル型推論(var
)を利用できることがわかります。 JEPは、次のコンパイルが期待されていると述べています。
var list = new ArrayList<String>(); // infers ArrayList<String>
以下を試みた場合、どうなるか知りたいです。
var list = new ArrayList<>();
2番目のスニペットで提案したものはコンパイルされますか?もしそうなら(私は疑問です)、ArrayList
はそのジェネリック型としてObject
を受け入れますか?
私はこれを自分で試しますが、初期リリースをインストールできるマシンにアクセスできません。
ありがとう!
はい、var
とdiamond演算子は組み合わせることができます。コンパイラーは、最も具体的なジェネリック型を推測します。
var list = new ArrayList<>(); // Infers ArrayList<Object>
var list = new ArrayList<>(List.of(1, 2, 3)); // Infers ArrayList<Integer>
また、それらを匿名クラスと組み合わせることもできます。
var list = new ArrayList<>() {};
「〜での作業」はあいまいな質問なので、あいまいな答えが得られる可能性があります。
型推論は読んでも問題ありません。それは単に制約を解くことです。使用できる型制約が少ないほど、失敗または予期しない結果(Object
などの予期しない型を推測すること)が発生する可能性が高くなります。
ダイアモンドは言う:私が必要とするタイプはおそらく左側にすでに存在している、なぜそれを右側に繰り返すのか。
ローカル変数の型推論によれば、私が必要とする型はおそらくすでに右側にあるので、なぜ左側で繰り返すのでしょうか。
ジェネリックメソッドの呼び出しは言う:私が必要とする型はおそらくすでに引数に存在している、なぜそれらを証人として繰り返すのか。
マニフェストコンストラクター型引数または左側のターゲット型なしで、プログラムで十分な型情報が利用できる場合、すべてが問題ありません。例えば:
List<String> anotherList = ...
var list = new ArrayList<>(anotherList);
ここで、コンパイラーは、コンストラクター(Collection<? extends E>
を受け取るもの)への引数の型を調べることにより、ArrayList
の型パラメーターを推測できます。したがって、RHSでT=String
を推論し、LHSでArrayList<String>
を推論することができます。
言い換えると、コンパイラーは、ユーザーが提供した情報を提供できることを実行します。提供する情報が少ないほど、失敗するか、期待どおりの結果が得られない可能性が高くなります。
とはいえ、あなたは間違った質問をしたと思います。どれだけ省略できるかという問題は、「コンパイラーがどれだけ除外できるか」ではなく、「プログラムの可読性にどれほどの損害を与えているか」という問題ではありません。コードを読むことは、コードを書くことよりも重要です。省略できる可能性のあるすべてのものを除外しても、読みやすさを最大化することはできません。 inのままにして、読者がプログラムに直面したときに混乱しないようにする必要があります。
はい、コンパイルされます。コード内のvar
var list = new ArrayList<>();
タイプArrayList<Object>
として推測されます(消去のために、要素の正確なタイプを正確に判別できないと思います)。これは、次のようなコードを使用する場合と同じです。
ArrayList list = new ArrayList<>();
// without the type of the element of list specified
ここで、list
は最終的にArrayList<Object>
と推定されます。
メーリングリストのFAQ からBrian:-
両側で推論を求めるとどうなりますか?
あなたが言うなら:
var x = new ArrayList<>()
次に、
List
への型引数とx
の型の両方を推測するようコンパイラーに要求します。しかし、コンパイラーが適切に機能するのに十分な型情報が提供されていません。
ほとんどの場合、あなたはあなたがあなたの心を読まれるように要求していることを告げる有益なコンパイラエラーを受け取ります。場合によっては、現在のように
Object
の推論にフォールバックします:Object o = new ArrayList<>() // always inferred ArrayList<Object> here