web-dev-qa-db-ja.com

Collections.emptyList()はList <Object>を返しますか?

ジェネリック型パラメーターを推測するためのJavaのルールをナビゲートするのに問題があります。オプションのリストパラメータを持つ次のクラスを検討してください。

import Java.util.Collections;
import Java.util.List;

public class Person {
  private String name;
  private List<String> nicknames;

  public Person(String name) {
    this(name,Collections.emptyList());
  }

  public Person(String name,List<String> nicknames) {
    this.name = name;
    this.nicknames = nicknames;
  }
}

私のJavaコンパイラは次のエラーを出します:

Person.Java:9: The constructor Person(String, List<Object>) is undefined

ただし、Collections.emptyList()は、<T> List<T>ではなく、List<Object>型を返します。キャストを追加しても役に立たない

public Person(String name) {
  this(name,(List<String>)Collections.emptyList());
}

利回り

Person.Java:9: inconvertible types

emptyList()の代わりにEMPTY_LISTを使用する

public Person(String name) {
  this(name,Collections.EMPTY_LIST);
}

利回り

Person.Java:9: warning: [unchecked] unchecked conversion

次の変更により、エラーはなくなります。

public Person(String name) {
  this.name = name;
  this.nicknames = Collections.emptyList();
}

誰も私がここで実行しているタイプチェックルールとそれを回避する最良の方法を説明できますか?この例では、最終的なコード例で問題ありませんが、クラスが大きい場合は、コードを複製せずにこの「オプションのパラメーター」パターンに従ってメソッドを記述できるようにします。

追加クレジット:emptyList()ではなくEMPTY_LISTを使用するのが適切な場合

252
Chris Conway

あなたが遭遇している問題は、メソッドemptyList()List<T>を返したとしても、タイプを提供していないため、デフォルトでList<Object>を返すことです。 typeパラメーターを指定し、次のようにコードを期待どおりに動作させることができます。

public Person(String name) {
  this(name,Collections.<String>emptyList());
}

これで、直接代入を行うとき、コンパイラはジェネリック型パラメーターを見つけ出すことができます。型推論と呼ばれます。たとえば、これを行った場合:

public Person(String name) {
  List<String> emptyList = Collections.emptyList();
  this(name, emptyList);
}

その後、emptyList()呼び出しはList<String>を正しく返します。

426
InverseFalcon

使用したい:

Collections.<String>emptyList();

EmptyListの内容のソースを見ると、実際には単に

return (List<T>)EMPTY_LIST;
94
carson

emptyListメソッドには次のシグネチャがあります。

public static final <T> List<T> emptyList()

Word Listの前の<T>は、結果が割り当てられる変数の型からジェネリックパラメーターTの値を推測することを意味します。したがって、この場合:

List<String> stringList = Collections.emptyList();

その後、戻り値はList<String>型の変数によって明示的に参照されるため、コンパイラーはそれを把握できます。この場合:

setList(Collections.emptyList());

コンパイラーがジェネリック型を判別するために使用する明示的な戻り変数はないため、デフォルトはObjectになります。

26
Dan Vinton