Java 与嵌套泛型集合的混淆

Java 与嵌套泛型集合的混淆,java,generics,collections,covariance,contravariance,Java,Generics,Collections,Covariance,Contravariance,请帮助我了解为什么add1()和add4()报告错误,以及为什么add2()和add3()不报告错误。具体来说,如果编译器允许编译其中的每一个,请给出不希望出现的后果的示例 class InnerTypeConfusion { interface Animal {} class Dog implements Animal {} class Room<T> { void add(T t) {} } void add1(Room<? ex

请帮助我了解为什么
add1()
add4()
报告错误,以及为什么
add2()
add3()
不报告错误。具体来说,如果编译器允许编译其中的每一个,请给出不希望出现的后果的示例

class InnerTypeConfusion {
   interface Animal {}
   class Dog implements Animal {}
   class Room<T> {
      void add(T t) {}
   }

   void add1(Room<? extends Animal> room) {
      // Error: The method add(capture#1-of ? extends Animal) in the type 
      // Room<capture#1-of ? extends Animal> is not applicable for the 
      // arguments (Dog)
      room.add(new Dog());
   }

   void add2(Room<Animal> room) {
      room.add(new Dog());
   }

   class Cage<T> {}

   void add3(Room<Cage<? extends Animal>> room) {
      room.add(new Cage<Dog>());
   }

   void add4(Room<Cage<Animal>> room) {
      // The method add(Cage<Animal>) in the type Room<Cage<Animal>> is not 
      // applicable for the arguments (Cage<Dog>)
      room.add(new Cage<Dog>());
   }
}
类内部类型混淆{
界面动物{}
类Dog实现动物{}
教室{
void add(T){}
}
无效添加1(房间用于
添加1

// We don't want to add a Dog to a room of cats...
Room<Cat> cats = new Room<Cat>();
add1(cats);
Cat cat = cats.get(0);
//我们不想在猫的房间里添一只狗。。。
房间猫=新房间();
地址1(猫);
Cat=cats.get(0);

对于
add4
,我们不想将
Cage
添加到
Cage
房间
Cage
不是
Cage
,尽管在方法
void add1中它是
Cage(房间当你使用一个未知类型的列表,标记为
,该列表几乎是只读的。你只能在其中插入
null
。你不能使用列表中的项目。这里你处理的是
动物的一个未知子类

void add1(List<? extends Animal> list) {
   list.add(new Dog());
}

谢谢,所以现在我清楚地明白了为什么
add1()
不应该编译,但是现在我不明白为什么
add3()
编译正确。谢谢,所以现在我清楚地明白了为什么
add1()
不应该编译,但是现在我不明白为什么
add3()
编译正确。@glenviewjeff这是错误的,所以我删除了它,用不同的措辞重写了它。@glenviewjeff好的,写了关于这个主题的详细解释。希望这会有帮助。Max我希望你不要介意我大量编辑了你的答案,而不是添加了我自己的答案。非常感谢——通过这个问题,我学到了很多东西!@glenviewjeff没问题,谢谢你的添加,也许有人会发现它和你一样有用:)Adrian,我不确定你在你的
add1
版本中添加了对
Animal
的强制类型,你想显示什么。你只是在显示隐式强制类型吗?你知道这个版本的
add1()
也不会编译,对吗?@glenviewjeff他说的是,如果你的方法参数定义为
Cage,我喜欢你解释
add1
的只读维度。它是只读的,因为无法确定列表的实际类型。但是,我不明白你在粘贴
ad时的意图d4
未修改。你是想更改某些内容以使其编译吗?@glenviewjeff否我本想回复他发布的代码,所以我将代码包括在内。我希望它能让我的回复更清楚,因为你知道我指的是代码的哪一部分。
Room<Cage<? extends Animal>> room = new Room<Cage<? extends Animal>>();
add3(room);
// Here we create a room that can contain only dog cages
Room<Cage<Dog>> room = new Room<Cage<Dog>>(); 

// But the method needs a "any kind of animal cage" room
// Therefore we get error during compilation
add3(room); 
void add(Room<Cage<? super Dog>> room) {
   room.add(new Cage<Dog>());
   room.add(new Cage<Animal>());
}
void add1(List<? extends Animal> list) {
   list.add(new Dog());
}
void add4(List<Cage<Animal>> list) {
   list.add(new Cage<Dog>());
}