泛型通配符<? extends T>和<? super T>

 java使用了泛型来保证数据的安全性,避免了什么乱七八糟的

东西都往容器里扔的情况。一般情况下我们使用<T>来定义泛型,

例如下面这块代码

public <T> T[] toArray(T[] a)

但是有时我们也会使用<? extends T>和<? super T>,这里简单介绍下

<? extends T>被称为 上界通配符,意为可以存入的类型包括T以及T的子类,例如

1     public T orElseGet(Supplier<? extends T> other) {
2         return value != null ? value : other.get();
3     }

<? super T> 被称为下界通配符,意为可以存入的类型包括T以及T的父类,例如

1     default Predicate<T> and(Predicate<? super T> other) {
2         Objects.requireNonNull(other);
3         return (t) -> test(t) && other.test(t);
4     }

也有同时使用的情况

1 default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
2         Objects.requireNonNull(before);
3         return (V v) -> apply(before.apply(v));
4     }

验证代码如下,我们发现无法将<? extends Father>与GrandFather关联,

同样的,无法将<? super Father>与Child关联

 1 public class PorblemSolution {
 2     
 3     public static void main(String[] args){
 4 
 5         Person<Father> p1 = new Person<Father>();
 6         
 7         Person<? extends Father> p2 = new Person<Child>(new Child());
 8         Person<? extends Father> p3 = new Person<Father>(new Father());
 9         // Person<? extends Father> p4 = new Person<GrandFather>(new GrandFather());
10         // Type mismatch: cannot convert from Person<GrandFather> to Person<? extends Father>
11         
12         Person<? super Father> p5 = new Person<Father>(new Father());
13         Person<? super Father> p6 = new Person<GrandFather>(new GrandFather());  
14         // Person<? super Father> p7 = new Person<Child>(new Child());
15         // Type mismatch: cannot convert from Person<Child> to Person<? super Father>
16         
17     }
18 }
19 
20     
21 class GrandFather{
22     GrandFather(){};
23 }
24 
25 class Father extends GrandFather{
26     Father(){};
27 }
28 
29 class Child extends Father{
30     Child(){};
31 }
32 
33 class Person<T> {
34     
35     private T item;
36     
37     Person(){};
38     
39     Person(T t){
40         item = t;
41     }
42     
43     public void set(T t){
44         item=t;
45     }
46     
47     public T get(){
48         return item;
49     }
50 }

<? extends T>和<? super T>为我们使用泛型提供了更多的实现方案,使得泛型的匹配不只局限于T本身。

但是,这两个通配符在使用过程中会泛型中类异常的风险增加,这里可以套用父类子类强制类型转换的思路去理解。

更详细的解释可以看这里https://www.zhihu.com/question/20400700

另外,我们需要知道java中的泛型是伪泛型,是加在编译层面的校验机制,在运行时是没有泛型这个东西的

有兴趣的可以了解下泛型擦除这个机制,这里还是给个样例

1 Person<Father> p1 = new Person<Father>();        
2 Person<? extends Father> p2 = new Person<Child>(new Child());    
3 System.out.println(p1.getClass());  // class JavaTest.Person
4 System.out.println(p2.getClass());  // class JavaTest.Person
5 System.out.println(p1.getClass() == p2.getClass()); // true
争取早日不再是一只菜鸡
原文地址:https://www.cnblogs.com/jchen104/p/15043270.html