java 。集合中的通配符

标签 java collections wildcard

java 。集合中的通配符

我在理解 Collections 中的通配符时遇到了很多困难,即使在阅读了 Stack Overflow 和各种教程网站中的类似帖子之后也是如此。我在下面做了一个非常简单的例子。你能解释一下我会如何在 Collection< myClass > 之间做出选择吗? , Collection< ? Extends MyClass > , 和 Collection< ? Super MyClass >

package z5;
import java.util.ArrayList;
public class Z5 {
public static class Animal{
}
public static class Mammal extends Animal{   
}
public static class Reptile extends Animal{   
}
public static class Lion extends Mammal{   
}
public static class Tiger extends Mammal{   
}
public static class Snake extends Reptile{
}           
    public static void main(String[] args) {
        ArrayList<Mammal> catHouse1 = new ArrayList<Mammal>();
            catHouse1.add(new Lion());
            catHouse1.add(new Tiger());  
            catHouse1.add(new Mammal());
            catHouse1.add(new Animal()); //ERROR  
        ArrayList<? super Mammal> catHouse2 = new ArrayList<Mammal>();
            catHouse2.add(new Lion());
            catHouse2.add(new Tiger());
            catHouse2.add(new Mammal());
            catHouse2.add(new Animal()); //ERROR  
        ArrayList<? extends Mammal> catHouse3 = new ArrayList<Mammal>();
            catHouse3.add(new Lion());  //ERROR
            catHouse3.add(new Tiger());  //ERROR
            catHouse3.add(new Mammal());  //ERROR
            catHouse3.add(new Animal()); //ERROR 
        ArrayList<Mammal> zooMammals = new ArrayList<Mammal>();
            zooMammals.addAll(catHouse1);  
            zooMammals.addAll(catHouse2);  //ERROR
            zooMammals.addAll(catHouse3);
        ArrayList<Animal> zooAnimals = new ArrayList<Animal>();
            zooAnimals.addAll(catHouse1);
            zooAnimals.addAll(catHouse2);  //ERROR
            zooAnimals.addAll(catHouse3);        
    }
}

在上面的示例中,我创建了类的层次结构。 Animal是Mammal和Reptile的父类(super class),Mammal是Lion和Tiger的父类(super class)。

我为动物园中的三个猫屋制作了 ArrayList。第一个只是 ArrayList< Mammal >。我可以添加任何哺乳动物类型或其子类的对象。

第二个是 ArrayList< ? super 哺乳动物>。我还可以添加 Mammal 类型的任何对象或其子类。

第三个是 ArrayList< ?延伸哺乳动物>。我不能添加任何东西。

最后,我将我的三个猫屋添加到动物园 Collection 中。 Animal 和 Mammal 是这里的主要父类(super class),无论接收方 ArrayList 持有哪种类型,行为都是相同的。 ArrayList < Mammal > 和 ArrayList 可以添加到动物园中。 ArrayList 不能。

这是我的问题:


1) 如果我想创建一个包含某个父类(super class)的所有子类的数组,为什么需要通配符?难道我不能只声明所有 ArrayList< Superclass > 并获得我需要的功能吗?

2) 我知道“< ? extends superclass >”接受父类(super class)及其所有子类。因此,<? extends Mammal >”接受 Mammals、Lions 和 Tigers。这听起来与“< Mammal >”完全一样。有什么区别?

3) 我读到“< ? super className >”接受任何类名的父类(super class)。这听起来不对。在上面的例子中,Lions 不是 Mammals 的父类(super class),但是“< ? super Mammal >”接受 Lions。 Animals 是 Mammals 的父类(super class),但是“< ? super Mammal >”不接受它。我想我那里的信息有误。

4) 如果“< ? extends superclass >”是只读的,我该如何开始填充它?拥有一个只能读取的空列表有什么意义?

5) 为什么 addAll 方法对“< ? super className >”不起作用?

我知道这些是基本问题,而且我知道之前已经有人回答过这些问题。我试图给出一个尽可能简单的代码示例,并希望能给我一个尽可能清晰的答案。提前感谢您提供的任何建议。

最佳答案

我不会详细介绍。

List<Animal>意思是:这个列表包含 Animal 的实例。所以你可以添加任何你想要的 Animal,并且当你从这个列表中获取元素时你一定会得到一个 Animal。

List<? extends Animal>意思是:这个列表是一个泛型列表,但是我们不知道泛型类型的类型。我们所知道的只是泛型类型是 Animal 或 Animal 的任何子类。所以它可能是 List<Animal> , 一个 List<Reptile>List<Lion> , 例如。但我们不知道。所以,当从这个列表中获取一个元素时,您一定会得到一个 Animal。但是你不会被允许在列表中添加任何东西,因为你不知道它的类型。如果您被允许添加一些东西,您可以将 Lion 存储在 List<Reptile> 中。 ,并且该列表将不再是类型安全的。

List<? super Animal>意思是:这个列表是一个泛型列表,但是我们不知道泛型类型的类型。我们所知道的只是泛型类型是 Animal,或者 Animal 的任何父类(super class)或超接口(interface)。所以它可能是 List<Animal>List<Object> , 例如。所以,当从这个列表中获取一个元素时,你可以肯定地说它是一个对象。不过,您可以肯定的是在此列表中添加您想要的任何动物,因为 List<Animal>List<Object>接受 Animal、Lion、Reptile 或 Animal 的任何子类。

大多数时候,您将这些通配符用作方法的参数。

当一个方法将列表作为参数并且只对从列表中读取感兴趣(即列表是生产者)时,您将使用 List<? extends Animal> .这使您的方法更具可重用性,因为它可以与 List<Animal> 一起使用, 还有一个 List<Reptile> , 一个 List<Lion>

当方法将列表作为参数并且只对向列表中添加元素感兴趣时(即列表是消费者),您将使用 List<? super Animal> .这使您的方法更具可重用性,因为它可以与 List<Animal> 一起使用, 还有一个 List<Object> .

此规则称为 PECS:Procucer:扩展;消费者: super

如果您的方法将列表作为参数并且必须从列表中获取和添加元素,您将使用 List<Animal> .

关于 java 。集合中的通配符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20165793/

相关文章:

java - "invalid use of @throws"在类路径中有 log4j-core 时编译错误

java - 从 JPA/Hibernate 中的 View 加载实体

java - 在 Websphere 8.5.5.10 中添加 TLS 1.2 后出现 Unsupported SignatureAndHashAlgorithm 错误

java - 为什么 TreeSet 抛出 ClassCastException?

windows - MinGW GCC 通配符

bash find 命令拒绝使用通配符查找多个文件

java - Java 中的不同游戏状态

java - HashSet 和 LinkedHashSet

java - 需要知道碰撞何时开始和结束 box2d

javascript - 由通配符证书和不同 CA 上的站点特定证书共享的 Cookie?