Java—泛型中的通配符

通配符类型

通配符有 3 种形式

  • < ? > 被称作无限定的通配符
  • < ? extends T> 被称作有上限的通配符。
  • < ? super T> 被称作有下限的通配符。

1>无限定通配符

public void testWildCards(Collection<?> collection){
}

上面的代码中,方法内的参数是被无限定通配符修饰的 Collection 对象,它隐略地表达了一个意图或者可以说是限定,那就是 testWidlCards() 这个方法内部无需关注 Collection 中的真实类型,因为它是未知的。所以,你只能调用 Collection 中与类型无关的方法(即不能向collection中添加新元素)


2> < ? extends T> 和 < ? super T>

  • 很多人写博客的时候都把这两点分开写,并且对其中的一些蕴含的原理含糊其辞一笔带过,其实这里又涉及到了我们的继承和多态的知识,下面看这个例子:
    首先,我们构建四个类
class GrandF{

}
class Father extends GrandF{

}
class  Son extends Father{

}
class GrandS extends Son{

}

下面是这四个类之间的继承关系

image.png

当我们执行这段代码时:

class TestSub {
    public void testSub(Collection<? extends GrandF> para){
        para.add(new GrandF());             //Error    
        para.add(new Father());             //Error    
        para.add(new Son());                //Error    
        para.add(new GrandS());             //Error    
    }
}
  • 以上四句代码编译器都会报错。很多人会疑惑:明明声明了集合内元素的类型必须是GrandF或它的的子类,那我为什么就不能add进去呢?
    这里我们看上面的继承关系图,其实就是一句话:子类是父类类型的,但父类不是子类类型的

< ? extends GrandF> 其实就是对集合内元素类型的约束,没错,它是要求这个集合内元素类型必须在这个范围内,但是一旦它以参数形式传入时,就确定了它的类型,但在这段代码块中,编译器只能确定,传入的集合的元素类型是GrandF或它的的子类,但当元素是GrandF的子类时,父类GrandF并不属于子类类型,自然不能add进去(类型不匹配)。同理,Father类,Son类,GrandS类都不能add进去,因为你只知道上界在GrandF处,但无法确定下界到底在哪里,所以无法向其中添加新的元素

  • 很多博客在这里只说明了在使用?通配符时无法进行写操作,我觉得这样解释并不全面,也没有道出其中的原理

但当我们执行代码:

class TestSub {
    public void testSub(Collection<? super GrandF> para){
        para.add(new GrandF());
        para.add(new Father());
        para.add(new Son());
        para.add(new GrandS());
    }
}

编译器居然没有报错!很多小伙伴都惊呆了,但如果看到这里也感到惊讶的话就证明你没有理解上面的那一段话,我们再来解释一遍:

在这段代码中,要求集合中元素的类型必须是GrandF或其父类,但是无论这个集合中元素类型是谁,它肯定是 GrandF,Father,Son,GrandS的父类,没错,又是那句话:

  • 子类是父类的类型,但父类不是子类的类型

在这里 我们指定了下界是GrandF 但是不知道上界到底在哪里。所以这个时候,我们所看到的这四个类,都属于GrandF或其父类的类型,所以都可以add进去

上面的这些东西确实有些绕,理解起来也有些困难,但这确实是多态与泛型结合的一个典型问题,一定要理解,可以自己敲几遍代码测试。

  • 最后总结一下,? extends 是上界通配符(已知上界但不知道下界) ? super 是下界通配符(知道下界但不知道上界)。只有当我们能确定下界时,我们才能确定我们add进去的元素类型都是属于 这个下界或这个下界的父类的类型(多态)。其实就是一句话,在有通配符的地方,只能对下界及下界以下的类的对象进行写的操作

猜你喜欢

转载自blog.csdn.net/wintershii/article/details/81215144