【问题标题】:Generics: LowerBounded wildcard vs UpperBounded wildcard泛型:LowerBounded 通配符与 UpperBounded 通配符
【发布时间】:2020-03-20 16:06:57
【问题描述】:

我了解 PECS(生产者扩展,消费者超级)的概念,但仍然对这些符号感到困惑:

public class PECSTest {
    public static void main(String[] args) {
        //List<? extends Object> ProducerList = new ArrayList<String>();
        //ProducerList.add("1"); // Line 1 :compileTimeError

        PECSTest myTest = new PECSTest();
        List<String> myList = new ArrayList<String>();
        myList.add("abc");
        myTest.printMyList(myList);
    }

    private void printMyList(List<? extends Object> myList) {
        // TODO Auto-generated method stub
        int i=0;
        while(i<myList.size()) {
            System.out.println(myList.get(i).getClass()); //Line 2
            System.out.println(myList.get(i).charAt(0)); // Line 3
            System.out.println(myList.get(i).equals(new String("abc")));
            i++;
        }
    }
}
  • 即使我创建了一个列表,它可以接受任何扩展 Object 类的对象,但是当我尝试添加字符串时,它在第 1 行给出了编译时错误。为什么?
  • 在第二种情况下,当我将 List 传递给 printMyList 方法时,它会在第 2 行打印 String 中的每个元素类类型,但在第 3 行,为什么我无法调用任何 String 类特定方法,例如 charAt。还有为什么不需要对 String 进行强制转换。

还有消费者

 List<? super Number> myList = new ArrayList<Object>();
 myList.add(new Object());// compile time error

为什么我不能在 myList 中添加对象。因为如果我们使用 super 这意味着这个列表可以包含等于和高于 Java 类层次结构中的数字的对象。所以 new Object() 应该根据该语句添加到列表中。

谢谢。

【问题讨论】:

  • 你不能像new Object()一样实例化一个“通用”Object
  • 为什么在Number (List&lt;? super Number&gt;) 上使用下界通配符?可能是List&lt;? extends Number&gt; 允许Number 的每个子类,而不是每个不是数字的对象...

标签: java generics wildcard pecs


【解决方案1】:

List 已经是一个泛型,所以你不应该将它的类型设置为泛型;如果您希望它接受所有类型,请将其类型设置为Object;此外,您不应在实例化中指定类型,因为 Java 可以从类型声明中推断出它:

List<Object> ProducerList = new ArrayList<>();

感谢 Java PolymorphismProducerList 现在允许所有类型,因为所有类都是 Object 类的特化。

由于printMyList 的参数myList 接受不止一种类型,因此您必须在强制转换之前检查其传递的类型以调用其方法,例如charAt()String

if (myList.get(i) instanceof String) { 
    System.out.println(((String)myList.get(i)).charAt(0)); // Line 3
}

完整的工作代码:

import java.util.*;

class PECSTest
{
    public static void main(String[] args) {
        List<Object> ProducerList = new ArrayList<>();
        ProducerList.add("1"); // Line 1

        PECSTest myTest = new PECSTest();
        List<String> myList = new ArrayList<String>();
        myList.add("abc");
        myTest.printMyList(myList);
    }

    private void printMyList(List<? extends Object> myList) {
        int i=0;
        while(i<myList.size()) {
            System.out.println(myList.get(i).getClass()); //Line 2
            if (myList.get(i) instanceof String) { 
                System.out.println(((String)myList.get(i)).charAt(0)); // Line 3
            }
            System.out.println(myList.get(i).equals(new String("abc")));
            i++;
        }
    }
}

输出:

class java.lang.String
a
true

附注:为什么在Number (List&lt;? super Number&gt;) 上使用下界通配符?可能是List&lt;? extends Number&gt; 允许Number 的每个子类,而不是每个不是NumberObject...

【讨论】:

  • “在第一种情况下,您可能不会在实例化中指定类型,因为 Java 可以从类型声明中推断出它:”但 java 允许这样做。使用 List ProducerList = new ArrayList();那么为什么我在添加字符串对象时会出错。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-16
  • 1970-01-01
相关资源
最近更新 更多