• Java的协变(extends)和逆变(super),说白了都是子类的实例赋值给父类的变量


    总的来说,协变和逆变   都是  子类的实例赋值给父类的变量。

    为啥呢, 你要想把父类的实例赋值给子类的变量,那是要报错的

    PECS (Producer Extends,Consumer Super)

    当客户端是producer,就意味着客户端生成的数据插入你的集合中,你的参数是父类,客户端的数据是子类,所以用extends

    当客户端是consumer,就意味着客户端从你的集合里面取数据,你的参数是子类,客户端的数据是父类,所以用super

    如下代码: java.util.Collections的copy方法(JDK1.7) 

    src, 顾名思义,就是源数据, copy方法要从src中取数据,所以用extends

    desc,就是目标数据,copy方法把数据插到desc中,所以用super。

    为啥呢?

    假设 T 是copy方法中使用的类型。

    src的类型我们就叫  input,  input extends T,所以input就是T的子类,

    desc的类型我们就叫output,   output super T, 所以output就是T的父类。

    所以 input就是output的子类。

     那么copy中的 di 就是ListIterator<Output>,    si 就是ListIterator<Input>

    di.set(si.next());    这句话就是把 input 赋值给output。  说白了,就是把 子类的实例赋值给父类的变量。

    协变是从 input到  T,  就是从调用方给你的方法数据。  调用方就是数据的产生者。用extends

    逆变是从 T 到 output, 就是你的方法给调用方数据。 调用方就是数据的消费者。用super

    重要:要注意T的位置,

    <? extends T>      ,                T在extends的右边, T是父类,    ?是子类。  ?才是真实的类型, 接收变量的类型是T

    <T extends BaseClass>  ,   T在extends的左边, T是子类。 T是真实的类型,接收变量的类型是  BaseClass

    <? super T>   ,                    T在super的右边,  T是子类 ,   ?是父类。  ?才是真实的类型,接收变量的类型是?

    <T super BaseClass>   ,       T在super的左边,  T是父类。     T是真实的类型,接收变量的类型是T

  • 相关阅读:
    带不带protype的区别
    一些方法(自己的认知)
    事件
    简单笔记
    freemarker Velocity获取request,session
    Freemaker中使用中括号来包含标签
    FreeMarker自定义标签
    Velocity模版自定义标签
    前端常用代码
    Eclipse中配置Ehcache提示信息
  • 原文地址:https://www.cnblogs.com/yfdream/p/7878764.html
Copyright © 2020-2023  润新知