ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

2021-10-25

2021-10-25 21:01:33  阅读:127  来源: 互联网

标签:10 25 通配符 List 类型 add 2021 泛型 data


泛型概念

java 泛型,是java SE 1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。这种参数类型可以用在类、接口和方法的创建中,分别称为【泛型类】、【泛型接口】、【泛型方法】。

一.通配符的应用
实践检验真理,所以在说明通配符上下界的理解的时候,先说明下什么时候使用通配符

关于泛型
类型通配符的作用是为了代替泛型类的类型实参。

当我们使用泛型类作为参数时,我们不想固定具体的泛型类型实参,而是想接收任意类型,或者某个类及其子类或超类类型作为类型实参,这个时候就需要使用通配符了,使用泛型类<?>作为类型实参
总结来说通配符解决的问题就是:类B是类A子类,但是泛型类不是泛型类的子类,但是我们又想有这么个类型能同时接收泛型类和泛型类类型作为参数的问题

通配符类型

无边界通配符:<?>
使用无边界通配符可以让泛型接收任意类型的数据

上边界通配符 :<?extends 具体类型 >
使用固定上边界的通配符的泛型可以接收指定类型及其所有子类类型的数据,这里的指定类型可以是类也可以是接口

下边界通配符 :<? spuer 具体类型>
所有固定下边界的通配符的泛型可以接收指定类型及其所有超类类型的数据。

通配符无法同时指定上下边界

举个栗子:
我们常用的List就是一个泛型类,以java.lang.Number类及其子类,超类作为类型实参,具体继承关系如下:

看下下面这段代码:

private List<? extends Number> data;
 
    private void test() {
        List<Number> numbers = new ArrayList<>();
        List<Integer> integers = new ArrayList<>();
        //List<Number> data = integers; //编译报错
        data = numbers;
        data = integers;
    }

显然虽然Integer是Number的子类,但是List并不是List的子类,所以List类型的变量不能直接赋值给List的变量。这时候通配符就起到作用了List<? extends Number>可以看做是List和List的子类,它可以接收Number类或者其子类型作为类型形参的泛型数据。
所以当我们要在一个方法或者类中接收不固定类型实参的泛型数据,可以考虑使用通配符

二.关于通配符的上下界

  1. 无边界 和 上边界通配符
    使用无边界和上边界通配符的泛型不能赋值(除了null),可以取值,但是只能去指定的类型及其超类类型(无边界只能取Object类型数据)

(无边界其实上边界就是Object)

以List为例:下面这段代码当我们用List<?>或者List<? extends Number>add数据时发现都会编译报错。
为什么:根据上面应用的结论,List、List、List这些类型可以理解为List<?>或者List<? extends Number>的子类型。
这时候List<?>或者List<? extends Number> add时候不知道到底要往List、List、List还是其他Number子类型的List中add数据的是Integer、Long还是Double类型。这么操作可能会引发类型不一致的问题,这显然和泛型的设计是相悖的。因此Java为了保证类型一致,是不允许这么操作的。但是null是所有引用类型都有元素,所有可以add成功。

List<?> data = new ArrayList<>();
List<?> data = new ArrayList<>();
data.add(new Object()); //编译报错
data.add(10);  //编译报错
data.add(null);
 
 List<? extends Number> numbers = new ArrayList<>();
numbers.add(10); //编译报错
numbers.add(new BigDecimal(20)); //编译报错
numbers.add(null);

在看一下get取值方法:
下面代码可以看出(忽略运行错误啊,只是为了说明泛型编译问题):get方法是可以取到指定类型及其超类型的数据。

List<?> data = new ArrayList<>();
Object object = data.get(0);

List<? extends Number> numbers = new ArrayList<>();
Number number = numbers.get(0);
Object number2 = numbers.get(0);
2.下边界通配符
与无边界和上边界通配符相反,下边界通配符只能取Object类型的数据,但可以赋值,只要是指定类型或者其子类型都能成功赋值

还是以List类为例,代码如下,对应到List里面就是add指定类型及其子类型数据时可以正常编译通过,但是get方法不能编译通过
为什么:因为Long、BigDecimal、Float都是Numer的子类,根据之前的结论? super Number代表可以接收指定类型及其父类型的数据,所以List<? super Number>可以理解为List或者List的父类型,显然List或者List是可以add Numer的子类型数据的。但是get的时候因为不知道具体是
List还是List或者是之间的什么类型,所以只能get所以类型的父类型Object`类型

List<? super Number> data = new ArrayList<>();
data.add(10);
data.add(new BigDecimal(1000));
data.add(10.07f);
data.add(new Object()) //编译报错
 
Object object = data.get(0);
Number number = data.get(0); //编译报错

标签:10,25,通配符,List,类型,add,2021,泛型,data
来源: https://blog.csdn.net/weixin_44093366/article/details/120960124

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有