- 假设:Men extends Person
- 但是不能 List<Person> list = new List<Men>(); 会报错!
- 因为: Men is-a Person 存在继承关系
- 但是:List<Men> is-not-a List<Person> 不存在继承关系
- 这让泛型用起来很不舒服,为解决这个问题,所以:
- ? 通配符类型
- <? extends T> 表示类型的上界,表示参数化类型的可能是T 或是 T的子类
- <? super T> 表示类型下界(Java Core中叫超类型限定),表示参数化类型是此类型的超类型(父类型),直至Object
- 现在:List<?extends Person> list = new List<Men>(); 就合法了。
请记住PECS原则:生产者(Producer)使用extends,消费者(Consumer)使用super。
生产者使用extends
List<? extendsPerson>表示该list集合中存放的都是Person的子类型(包括Person自身),由于Person的子类型可能有很多,但是我们存放元素时实际上只能存放其中的一种子类型(这是为了泛型安全,因为其会在编译期间生成桥接方法<Bridge Methods>该方法中会出现强制转换,若出现多种子类型,则会强制转换失败)。因此你不能往该列表中添加任何元素,(因为你不知道里面到底存储的是什么类型)。List<? extends Person>不能添加元素,但是由于其中的元素都有一个共性--有共同的父类,因此我们在获取元素时可以将他们统一强制转换为Person类型,相当于一个只读List。
消费者使用super
对于List<? super Men>其list中存放的都是Men的父类型元素(包括Men),我们在向其添加元素时,只能向其添加Men的子类型元素(包括Men类型),这样在编译期间将其强制转换为Men类型时是类型安全的,因此可以添加元素。但是由于该集合中的元素都是Men的父类型(包括Men),其中的元素类型众多,在获取元素时我们无法判断是哪一种类型,故设计成不能获取元素,相当于一个只写List。