zoukankan      html  css  js  c++  java
  • 泛型通配符<? 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
    争取早日不再是一只菜鸡
  • 相关阅读:
    图论小测
    有关连通性
    差分约束
    php中代码执行&&命令执行函数【转载】
    Boss直聘的一个csrf与url跳转漏洞(已经修复)
    Immunity Canvas初体验加操作指南
    SSRF复习版本
    XXE漏洞复习版本
    信息收集汇总
    web前端逆向初体验
  • 原文地址:https://www.cnblogs.com/jchen104/p/15043270.html
Copyright © 2011-2022 走看看