0

でジェネリックを理解したと思いましたsuper。しかし、私は完全に間違っているに違いありません:

この簡単な例では:

class Animal{}
class Dog extends Animal{}

このコードは、Dog のスーパー クラスを渡しているため、正常に機能します。

static void addThis(ArrayList<? super Dog> a) {
    a.add(new Dog());
}
...
ArrayList<Animal> dogs=new ArrayList();
addThis(dogs);

しかし、私が理解していないのは、これは同じことだと思ったということです:

ArrayList<? super Dog> dogs2=new ArrayList();
dogs2.add(new Animal());

しかし、コンパイルに失敗します。2つの違いは何ですか?


ところで、こっそり別の質問をしたいと思います。間に違いはありますか

// This...
ArrayList<Animal> dogs=new ArrayList();
// ... and this?
ArrayList<Animal> dogs=new ArrayList<Animal>();

与えられた型の消去がコンパイル時にそれを削除すると、コンパイラが参照型をチェックしていることと同じだと思います。これは正しいです?

4

3 に答える 3

4

まったく同じではありません。を追加するDog場合もあれば、 を追加する場合もありますAnimal

どちらの場合も、 s が許可されていることしかわかっていないため、2 番目のケースは失敗します。Dog

2 番目の質問に答えるに、違いがあり、常に 2 番目のバージョンを使用する必要があります。(ただし、Java 7 以降では、 を記述することで、コンパイラーにジェネリック型を推測するように要求できますnew ArrayList<>()。)

于 2013-02-12T23:15:33.293 に答える
0

Dog は Animal なので to をキャストすることはできArrayList<? extends Dog>ますArrayList<Animal>が、Animal は必ずしも Dog であるとは限らないため、その逆はできません。

例えば:

public class Cat extends Animal{}

これは意味がないので:

ArrayList<Dog> dogList = new ArrayList<Dog>();
dogList.add(new Cat());

動物は猫である可能性があるため、犬リストに動物を追加することはできません。

これは Java タイプ セーフの例です。

于 2013-02-12T23:16:45.710 に答える