web-dev-qa-db-ja.com

Javaでジェネリックを使用してリストをキャストするにはどうすればよいですか?

次のスニペットを検討してください。

public interface MyInterface {

    public int getId();
}

public class MyPojo implements MyInterface {

    private int id;

    public MyPojo(int id) {
        this.id = id;
    }

    public int getId() {
        return id;
    }

}

public ArrayList<MyInterface> getMyInterfaces() {

    ArrayList<MyPojo> myPojos = new ArrayList<MyPojo>(0);
    myPojos.add(new MyPojo(0));
    myPojos.add(new MyPojo(1));

    return (ArrayList<MyInterface>) myPojos;
}

Returnステートメントは、コンパイルされないキャストを実行します。 myPojosリストをより一般的なリストに変換するにはどうすればよいですかリストの各項目を調べる必要はありません

ありがとう

26
Ry.

ワイルドカードを使用するようにメソッドを変更します。

public ArrayList<? extends MyInterface> getMyInterfaces() {    
    ArrayList<MyPojo> myPojos = new ArrayList<MyPojo>(0);
    myPojos.add(new MyPojo(0));
    myPojos.add(new MyPojo(1));

    return myPojos;
}

これにより、呼び出し元がインターフェイスのother実装をリストに追加しようとするのを防ぐことができます。または、次のように書くこともできます。

public ArrayList<MyInterface> getMyInterfaces() {
    // Note the change here
    ArrayList<MyInterface> myPojos = new ArrayList<MyInterface>(0);
    myPojos.add(new MyPojo(0));
    myPojos.add(new MyPojo(1));

    return myPojos;
}

コメントで議論されているように:

  • ワイルドカードコレクションを返すことは、発信者にとって厄介な場合があります
  • 通常、戻り値の型には具象型ではなくインターフェースを使用することをお勧めします。したがって、提案された署名はおそらく次のいずれかになります。

    public List<MyInterface> getMyInterfaces()
    public Collection<MyInterface> getMyInterfaces()
    public Iterable<MyInterface> getMyInterfaces()
    
41
Jon Skeet

最初から適切なタイプを選択するのが最善ですが、質問に答えるには型消去を使用できます。

return (ArrayList<MyInterface>) (ArrayList) myPojos;

24
Peter Lawrey

あなたはするべきです:

public ArrayList<MyInterface> getMyInterfaces() {   
   ArrayList<MyInterface> myPojos = new ArrayList<MyInterface>(0);    
   myPojos.add(new MyPojo(0));    
   myPojos.add(new MyPojo(1));    
   return myPojos;
}
4
Jacob Schoen

インスタンスを構築するときを除いて、どこでもインターフェースを使用するようにしてください。そうすれば、問題はなくなります。

public List<MyInterface> getMyInterfaces()
{
    List<MyInterface> myInterfaces = new ArrayList<MyInterface>(0);
    myInterfaces.add(new MyPojo(0));
    myInterfaces.add(new MyPojo(1));

    return myInterfaces;
}

他の人がすでに言っているように、MyInterfaceを使用すると問題が解決します。また、戻り型と変数には、ArrayListの代わりにListインターフェイスを使用することをお勧めします。

0
starblue

この場合、私は次のようにします:

public ArrayList<MyInterface> getMyInterfaces() {

    ArrayList<MyInterface> myPojos = new ArrayList<MyInterface>(0);
    myPojos.add(new MyPojo(0));
    myPojos.add(new MyPojo(1));

    return myPojos;
}

MyPojoはMyInterfaceタイプではありません(インターフェイスを実装しているため)。つまり、必要なインターフェイスを使用してリストを作成するだけです。

0
Tobias Langner