web-dev-qa-db-ja.com

「var」型とraw型はどのように組み合わされますか?

answer に出くわした

var list = new ArrayList();

ここで生の型を見つけて驚いたのですが、単純に疑問に思っています:var<>を自動的に使用しますか?

(その間、答えは<String>を使用するように変更されましたが、私はまだここに「原則」について興味があります)

this などの他の質問を見ましたが、すべてダイヤモンド演算子を使用しています:

var list = new ArrayList<>();

今、私は単に疑問に思っています:varは、未加工の型を使用する(しない)方法を変更しますか?それとも、<>単に悪い習慣を省くという提案ですか?

19
GhostCat

私は使用することを示唆する答えに出会いました...

私はその答えを無視します指摘したように、生のタイプを使用し、具体的にlistとしてArrayListを入力するためです。 (更新:回答者が編集 回答 要素タイプを追加します。)代わりに:

_List<AppropriateElementType> list = new ArrayList<>();
_

リンクした2番目の回答varwillによれば、_<>_を含めた場合、コンパイラーは右側から要素タイプを推測し、最も具体的なタイプ。 var list = new ArrayList<>();では、_ArrayList<Object>_になりますが、選択できる具体的なものがないためです。

しかし、、これ:

_var list = new ArrayList();
_

... _<>_を使用せずに、ArrayListをパラメーターとして使用するパラメーター化された型(_ArrayList<Object>_)ではなく、生の型(Object)を使用していますが、これは異なります。


listの使用が十分に含まれている場合(メソッド内の数行)、それを_ArrayList<X>_ではなく_List<X>_と入力することが許容される場合があります(コーディングスタイルによって異なります)。

_var list = new ArrayList<AppropriateElementType>();
_

しかし、一般的には、ローカルであっても、具体的なクラスよりもインターフェイスにコーディングすることを好みます。つまり、ローカルでは、インスタンスメンバよりも重要性が低いisであり、varが便利です。

32
T.J. Crowder

vardiamondの両方を使用することは正当ですが、推測される型は変更されます。

var list = new ArrayList<>(); // DANGEROUS: infers as ArrayList<Object>

推論のために、diamondはターゲット型(通常、宣言の左側)またはコンストラクター引数の型を使用できます。どちらも存在しない場合、最も広く適用可能なタイプにフォールバックします。多くの場合、Object1

diamondとジェネリックメソッドの両方で、実際の引数によって追加の型情報をコンストラクターまたはメソッドに提供し、目的の型を推測できるようにすることができます。1

var list = List.of(BigInteger.ZERO); // OK: infers as List<BigInteger>
var list = new ArrayList<String>( ); // OK: infers as ArrayList<String>

上記を考慮して、次のことはお勧めしません(生のArrayListタイプを取得するため)。

var list = new ArrayList(); // DANGEROUS: infers as ArrayList

結論:

  1. varの有無に関係なく、rawタイプを使用しないでください。
  2. メソッドまたはコンストラクタの引数が十分な型情報を提供し、推論された型が意図と一致するようにしてください。それ以外の場合は、vardiamondの両方を使用しないでください1

1- スタイルガイドライン Local Variable Type Inference:G6。 varをdiamondまたはジェネリックメソッドで使用する場合は注意してください。

10