Java 泛型中 ? super T 和 ? extends T 的区别

 2023-02-06
原文作者:蒋先森 原文地址:https://jlj98.top/

最近在看阿里出的一本书 —— 《码出高效 Java 开发手册》,这本书不是之前那本关于 Java 开发注意规范的手册,这本书内容还是不错的,干货满满。

在看书的时候,就看到了关于上面讲的知识点,于是想到之前在看 Java 一些源码时候,也看到一些关于这个泛型的写法,当时还没注意,比如下面关于 ThreadLocal 源码是看到的。

202212301147419991.png

这样以后看 Java 的源码就能看懂这些泛型的写法了。

和 是 Java 泛型中的 “通配符“和”边界”的概念。 - : 是指“上界通配符”。 A super B 表示 A 是 B 的父类或者祖先,在 B 上面。 - :是指“下界通配符”。A extends B 表示 A 是 B 的子类或者孙类,在 B 的下面。 与两种语法,但是两者的区别非常微妙。简单来说,是 Get first,适用于消费集合元素为主的场景;是 Put First,适用于生产集合元素为主的场景。 # 可以赋值给任何 T 及 T 子类的集合,上界为T,取出来的类型带有泛型限制,向上强制转型为T。null可以表示任何类型,所以除nul外,任何元素都不得添加进集合内。 # 可以赋值给任何 T 及 T 的父类集合,下界为T。在生活中,投票选举类似于 的操作。选举代表时,你只能往里投选票,取数据时,根本不知道是谁的票,相当于泛型丢失。有人说,这只是一种生活场景,在系统设计中。很难有这样的情形。再举例说明一下,我们在填写对主管的年度评价时,提交后若想再次访问之前的链接修改评价,就会被告之:“您已经完成对主管的年度反馈,谢谢参与。" extends的场景是put功能受限,而 super的场景是get功能受限。 # 集合和泛型 下面的代码和说明出自《码出高效,Java开发手册》

    public static void main(String[] args) {
    
            //第一阶段:泛型出现之前的集合定义方式
            List a1 = new ArrayList();
            a1.add(new Object());
            a1.add(new Integer(111));
            a1.add(new String("Hello World"));
    
            for (Object o : a1){
                System.out.println(o);
            }
    
            //第二段:把a1 引用赋值给a2,注意a2与a1的区别是增加了泛型限制<Object>
            List<Object> a2 = a1;
            a2.add(new Object());
            a2.add(new Integer(222));
            a2.add(new String("hello a2a2"));
    
            //第三段:把a1引用赋值给a3,注意a3与a1的区别是增加了泛型<Integer>
            List<Integer> a3 = a1;
            a3.add(new Integer(333));
            //下方两行编译出错,不允许增加非 Integer类型进入集合
            a3.add(new Object());
            a3.add(new String("hello a3a3"));
    
            //第四段:把a1引用赋值给a4,a1与a4的区别是增加了通配符
            List<?> a4 = a1;
            a1.remove(0);
            a4.clear();
            //编译出错。不允许增加任何元素
            a4.add(new Object());
    
        }

第一段说明:在定义List之后,毫不犹豫地往集合里装入三种不同的对象:Object、 Integer 和 String,遍历没有问题,但是贸然以为里边的元素都是 Integer,使用强制转化,则抛出 ClassCastException异常。 第二段说明:把a赋值给a2,a2是 List类型的,也可以再往里装入三种不同的对象。很多程序员认为List和List是完全相同的,至少从目前这两段来看是这样的。 第三段说明:由于泛型在JDK5之后才出现,考虑到向前兼容,因此历史代码有时需要赋值给新泛型代码,从编译器角度是允许的。这种代码似乎有点反人类,在实际故障案例中经常出现。 第四段说明:问号在正则表达式中可以匹配任何字符,List

称为通配符集合。它可以接受任何类型的集合引用赋值,不能添加任何元素,但可以 remove 和 clear,并非 immutable集合。List<?>一般作为参数来接收外部的集合,或者返回一个不知道具体元素类型的集合。

Reference

  • 《码出高效:Java开发手册》

客官,赏一杯coffee嘛~~~~

Donate

202212301147429422.png

WeChat Pay

202212301147440763.png

Alipay

# 泛型

Java 并发编程 —— AQS

Java 多态

  • Table of Contents
  • Overview
    1. Reference

202212301147449494.png

蒋先森

当你的才华还撑不起你的野心时,那你就应该静下心来学习

96 posts

23 categories

115 tags

GitHub

© 2022 蒋先森

|