千家信息网

Java泛型之协变、逆变、extends与super选择方法

发表于:2026-10-31 作者:千家信息网编辑
千家信息网最后更新 2026年10月31日,今天小编给大家分享一下Java泛型之协变、逆变、extends与super选择方法的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这
千家信息网最后更新 2026年10月31日Java泛型之协变、逆变、extends与super选择方法

今天小编给大家分享一下Java泛型之协变、逆变、extends与super选择方法的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。

要了解协变与逆变,首先要引入:

根据 Liskov替换原则,如果C是P的子类,则P可以代替C,即 P p = new C();
C继承于P,记做为 C < P

什么是不变

如果F是不变,当 C <= P 时,那么 F(C) 和 F(P) 没有任何继承关系

除例如 Integer是 Number的子类,根据 Liskov替换原则

Number number = new Integer(1);  //correct

但是如果这样写就会报错

List list = new ArrayList(1);  //error

虽然 Number和 Integer存在继承关系:Integer < Number, 但在Java里,泛型默认是不变的, 因此也可以看作为 List 和List 不存在任何继承关系

什么是协变

如果F是协变的,当 C <= P 时,那么 F(C) <= F(P)

Java 提供了一个extends来将不变转为协变,例如:

List list = new ArrayList(1);  //corrent

此时的List可以看作为ArrayList的父类

? extend Number可以看作为一个类型范围,表示Number的某一个子类

数组默认是协变的

Number[] numbers = new Integer[3];

什么是逆变

如果F是逆变的,当 C <= P 时,那么 F(C) >= F(P)

Java 提供了一个super来将不变转为协变,例如:

List list = new ArrayList(1);  //corrent

此时的 List可以看作为 ArrayList的父类

extends 和 super

首先,我们看看Collection.add的实现:

public interface List extends Collection { boolean add(E e); }

下面代码将会报错?? extends Number与Integer类型不匹配

List list = new ArrayList(); // correctlist.add(Integer.valueOf(1));  //error

首先在调用add方法时,泛型E自动变成了

第二行报错,也就是说? extends Number不是Integer的父类。这里要将 List是ArrayList的父类区分开。

? extends Number可以看作为一个类型范围中某一个类型,表示Number的某一个子类,但又没明确是哪个子类,可能是Float,可能是Short,也可能是Integer的子类(Integer被final修饰,不可能有子类,这里只是一种假设情况),它只确定了它的上界为 Number,并没有确定下界(有可能存在? extends Number< Integer),因此 ? extends Number不是Integer的父类

将上面代码稍做修改就正确了:

List list = new ArrayList(); // correctlist.add(Integer.valueOf(1));  //correct

首先因为逆变,List是ArrayList的父类,第一行正确。

第二行: ? super Number是Integer的父类,原因是:? super Number表示Number的某一个父类,可能是Serializable也可能是 Object 但不管是哪个,Number的父类一定是Integer的父类,因此第二行也正确

使用extends还是super呢

java.util.Collections的copy方法(JDK1.7)给了我们答案:

public static  void copy(List dest, List src) {    int srcSize = src.size();    if (srcSize > dest.size())        throw new IndexOutOfBoundsException("Source does not fit in dest");    if (srcSize < COPY_THRESHOLD ||        (src instanceof RandomAccess && dest instanceof RandomAccess)) {        for (int i=0; i di=dest.listIterator();        ListIterator si=src.listIterator();        for (int i=0; i
  • 要从泛型类取数据时,用extends;

  • 要往泛型类写数据时,用super;

  • 既要取又要写,就不用通配符(即extends与super都不用)

private static  E getFirst(List list){    return list.get(0);}private static  void setFirst(List list, E firstElement){    list.add(firstElement);}public static void main(String[] args) {    List list = new ArrayList();    setFirst(list, 1);    Number number = getFirst(list);}

以上就是"Java泛型之协变、逆变、extends与super选择方法"这篇文章的所有内容,感谢各位的阅读!相信大家阅读完这篇文章都有很大的收获,小编每天都会为大家更新不同的知识,如果还想学习更多的知识,请关注行业资讯频道。

子类 方法 知识 篇文章 类型 选择 不用 代码 内容 原则 数据 范围 会报 不同 很大 一行 上界 下界 也就是 也就是说 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 广州紫鲸互联网科技有限公司 厦门中拓互联网络科技有限公司 互联网是不是新科技 互联网中国科技 互联网 科技 互联网科技集团 互联网科技公司做什么 开启互联网科技时代小说 互联网汽车科技小镇 济南华为互联网科技产业总部基地 温州喔噻互联网科技有限公司 广州慧亚互联网科技怎么样 阿里互联网科技公司 哈尔滨屹滨互联网科技有限公司 国大互联网教育科技有限公司薪资 互联网领先科技宣传片 江苏互联网智能科技软件 西安有哪些互联网高科技企业 中国互联网公司的科技投入 中国主要互联网科技公司 互联网科技保险 科技互联网政务服务 互联网养老 桔豆科技 富国互联网科技创新基金 厦门千工互联网科技有限公司 苏州五指互联网络科技有限 华夏互联网科技业 中国互联网十大科技股排名 翼展科技 首家互联网医院 互联网科技如何创业
0