gpt4 book ai didi

java - 混淆嵌套泛型的集合

转载 作者:行者123 更新时间:2023-12-04 20:39:07 26 4
gpt4 key购买 nike

请帮我理解为什么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>());
}
}

最佳答案

在方法中void add1(Room<? extends Animal> room) ,您定义该方法接受 Room持有 Animal .例如,它可以是 Room<Cat> , 或 Room<Dog> --偶数Room<Animal>用于容纳所有类型的动物。但是,请记住,房间是在该方法调用之外创建的,您不能对房间类型做出任何假设,除非它拥有特定的动物。

add1(new Room<Dog>()); // give the method a room for dogs
add1(new Room<Cat>()); // give the method a room for cats
add1(new Room<Animal>()); // give the method a room for any animal

但是一旦进入该方法,您就无法具体知道通过了哪种类型的房间。

只有鸟的房间才能调用该方法 add1(new Room<Bird>()) , 作为 Bird确实扩展了 Animal .但是在方法主体中,您要添加一个 Dog进去。这就是为什么它无效,我们不能把 Dog对象进入 Room<Bird> .这是一个Room 一些动物而不是Room 任何种类的动物。

如果您想编写一个方法,将一只狗添加到适合添加狗的房间(但不限于仅限狗的房间),您可以使用签名 addDogToRoom(Room<? super Dog> room) 来编写它每this answer .此方法可以接受 Room<Animal>以及Room<Dog>并且仍然在方法内添加新的狗到房间。

关于add4 , 相同而相反。与 Room<Cage<Animal>>您指定该方法需要特定的房间类型——一个只允许容纳任何类型Animal的笼子的房间.但是你试图把 Cage<Dog>进入其中,一个笼子只允许狗。因此,它再次无效。

关于评论的补充:

假设有专为容纳猫而设计的笼子 Cage<Cat>和笼子设计用于容纳狗Cage<Dog> .还有万能笼子,可以放任何动物Cage<Animal> .这是三种不同的笼子,它们不能相互替代,因为它们具有完全不同的架构和设计。

  • void method(Cage<Dog>)意味着该方法需要一个狗笼。
  • void method(Cage<Animal>)意味着该方法需要一个通用笼。
  • void method(Cage<? extends Animal>)意味着该方法需要任何种类的动物笼子。狗笼、猫笼或通用笼。

房间是另一个抽象层次——将它们想象成一个里面有笼子的房间。可以有放猫笼的房间Room<Cage<Cat>> ,一个存放狗笼的房间Room<Cage<Dog>> ,一个存放通用笼子的房间Room<Cage<Animal>>和一个存放多种动物笼子的房间Room<Cage<? extends Animal>> .因此,同样的规则适用:

  • void method(Room<Cage<Dog>>) - 狗笼房间
  • void method(Room<Cage<Cat>>) - 猫笼子的房间
  • void method(Room<Cage<Animal>>) - 动物笼室
  • void method(Room<Cage<? extends Animal>>) - 可以容纳多种动物笼子的房间。例如,房间可以同时包含 Cage<Dog> , 和一个 Cage<Animal> .

现在,在 add3(Room<Cage<? extends Animal>> room) ,您要求最后一种房间,可以容纳“各种动物笼子”的房间。因此传递给该方法的房间可以包含或添加新的狗笼子room.add(new Cage<Dog>())或任何其他类型的笼子。

但是,要调用该方法,您需要先创建一个新的“通用”房间(支持所有笼子):

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>());
}

关于java - 混淆嵌套泛型的集合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9890866/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com