Java泛型通配符'?'的使用

声明:文中描述的某个类对象的引用,该引用指向的对象并非其子类的对象,而是真真实实的这个类的对象。

类层次关系

----------------------------Java泛型通配符'?'的使用_第1张图片

1. 下界通配符测试(代码块1-1)

void useLowerbBoundWildCard(List superGuidedFireArrowList)
    {
    	 /*for(Arrow arrow:superGuidedFireArrowList)
        {
        }*/
        //读取上界
        for(int i=0;i

1.1 分析

  List 表示这样的一个列表:

  存放的对象的引用都是该类的父类或者父类的父类乃至祖先类的对象。

  因此下面列出的所有列表:

  • List
  • List
  • List
  • List

      都可以是一个List

      那么从 List 读出来的元素可能是一个Object类的一个对象引用,可能是Arrow类的一个对象引用,也可能是一个FireArrow类的对象引用,或者一个GuildedFireArrow类的一个对象引用。由于不知道确切的是什么对象的引用,故使用时还需要判断一下对象的类型,使用getClass来判断(不用instanceof或者isInstance方法来判断,因为这两个方法即使作为参数的引用指向的是其子类的对象也会判断是这个类的实例)。

      可以往这个列表中加入任意类型的GuidedFireArrow类,因为不管列表中存放的是哪个类,指向GuidedFireArrow类对象的引用都可以隐式地转换(列表中存放的对象引用所属的类必然是GuidedFireArrow的父类引用,或者它本身)为这个类的引用。

    1.2 foreach循环应用于List

    for(Arrow arrow:superGuidedFireArrowList)
    {
    }

      在代码块1-1中有这样一段被注释掉的for循环,使用这段代码时,会报错。原因在于:
    从列表List 中取出的引用,不见得就一定能转换为类Arrow的引用,虽然类ArrowFireArrowGuidedFireArrowList这些类的父类或者祖先类,但是Arrow还有一个父类是Object类,因此如果这个list中存放的是Object类对象的引用,且引用指向的确实是Object对象,则等于把一个Object类对象引用转换为一个Arrow类对象引用这种是会触发ClassCastException异常。为了避免运行时出现错误,编译器索性在编译时就报错。

    2. 上界通配符测试(代码块2-1)

    void test(List arrowList)
        {
            for(Arrow arrow:arrowList)
            {
                
            }
        }
    

    2.1 分析

      List 表示这样的一个列表:

      存放的对象的引用都是继承Arrow类的子类的对象或其本身的对象的引用。

      因此下面列出的所有列表:

    • List
    • List
    • List(注意,即使是子类的子类,也算是继承这个类)
    • List

      都可以是一个List
      因此从这个列表中取出的每个引用都可以转换为Arrow引用。
      但是一旦出现这样的代码:

    void test(List arrowList)
        {
            arrowList.add(new Arrow());
        }
    

      IDE就会报错,因为这个List存放的对象引用可能是上述的某种,所以一旦一个存放FireArrow类对象的List被传入这个函数,然后想往其中添加一个Arrow类对象引用或者IceArrow对象引用,都会报错(运行时可能出现ClassCastException异常)。而无限制通配符List 中存放的对象引用更不知道是什么类型的,同样禁止往其中添加任何对象引用,除了可以表示任何对象引用的null引用。

    结论

    Effective Java有个"PECS"原则,即

    producer-extends,consumer-super

      使用上界通配符 的容器通常可以作为一个生产者,只能往外面吐东西,而不能往里面添加任何东西(除了null,null可以是任何对象的引用),使用下界通配符 的容器可以作为一个消费者,可以往里面写入东西,也可以往外面吐东西(相对来说比较麻烦,因为不清楚吐出的东西到底是什么对象的引用)。

    你可能感兴趣的:(Java)