孤独的守望者 -- 泛型

一:概述

为什么给这篇文章起名为孤独的守望者,说不上来,但是如果深入了解过Java中的泛型对这个标题都会有所感触。编译时存在作为类型安全检查,运行时被擦除回归本质,有没有那么一点感觉??不扯淡了,本文将从泛型定义、泛型通配符、泛型擦除三方面讲一下总是让人感觉很神秘的泛型

二:泛型的前世今生

没有泛型前集合类是怎么操作的?恐怕很多人马上都会得到答案,强转呗。强转的代码充斥在角角落落,如果类型错误需要程序运行才能发现错误恐怕不是一件喜闻乐见的事情。如下图所示,集合里面存储两个两个类型的东西居然不报错,哈哈哈,想想这是多么恐怖的事情。当然可能Object不太准确,不过无伤大雅
在这里插入图片描述
天空一声巨响,泛型必须登场。就像看门狗一样,编译期间直接检查类型是否合规,并且还能提升代码的可阅读性。任何人看到集合都可以通过泛型迅速定位集合内容类型,并且在获取数据时不用再执行危险的强转操作,如下图所示
在这里插入图片描述

三:泛型的用武之地

泛型可以在三个地方使用:

  • 接口
  • 方法

泛型定义一般采用大写字母,约定俗成有一下几点:

  • T:代表一般泛型
  • K:代表key值泛型
  • V:代表value泛型
  • E:代表exception异常泛型
  • S:代表子类型
3.1 泛型类

如下图所示,自定义一个泛型类,并使用类泛型定义一个属性,当属性赋值为不符合泛型类型时就会编译不通过。总结类泛型的定义与使用:

  • 类名后直接添加<泛型声明>
  • 类实例化声明泛型类型

在这里插入图片描述

3.2 泛型接口

泛型接口与泛型类其实就是一个爹生娘养的,就是在类、接口后面定义泛型就可以使用。用法也一样,直接拿起你定义的字母用就行
在这里插入图片描述

3.3 泛型方法

泛型方法声明泛型的位置就在修饰符之后,返回值之前
在这里插入图片描述
泛型方法的声明是为了什么?不就为了参数列表或者是返回值使用么,那么如下图所示,方法声明泛型之后可以直接在参数列表以及返回值使用
在这里插入图片描述
泛型方法在调用前就必须确定泛型类型,当然可以从参数列表反推获取到实际类型亦或是使用类、接口声明的泛型。如果你的方法调用不能确定泛型类型,编译就会报错
在这里插入图片描述
前面说到除了从参数列表确定泛型方法类型,还可以使用类、接口声明泛型。思考一下,如果是静态方法可以使用类、接口声明的泛型?恐怕想想就知道不可能,类的泛型需要在实例化时进行声明,但是静态方法却是在启动进行加载,这时候泛型还未声明确定,所以编译必然不能通过
在这里插入图片描述

四:泛型擦除
4.1 初识泛型擦除

朕的大清亡了,你们这些骗子,你String和TestClass有半毛钱关系,为什么相等?别着急,请听在下娓娓道来,相信自己的眼睛程序不会骗人。真相只有一个,泛型擦除搞的鬼
在这里插入图片描述

4.2 泛型擦除探究

首先解释两个集合为什么相等,孤独的守望者只是在编译期间有效,程序运行期间是没有泛型的,称之为泛型擦除。所以两个集合运行时类型并不是List<>,而是直接的List类型,结局自然也就相等。顺便看了一下属性的泛型,其实泛型擦除后回归的类型都是Object
在这里插入图片描述

五:泛型通配符

泛型通配符有一下三种表现形式:

  • ?:无限定通配
  • extends:有上限通配
  • super:有下限通配
5.1 无限定通配符

泛型不挺好用的么,为什么还要整一个无限定通配符出来混淆视听呢?难道是Orcle那帮人无所事事?看下面的例子你就知道得咯。为什么编译不通过,能通过就有鬼,你泛型擦除后集合都没有泛型了,谁知道这俩集合里面装的东西一样不一样,如果不一致你想想后面取用的时候有什么效果
在这里插入图片描述
所以为了在泛型中表示待定事物,则可以使用无限定通配符。无限定通配符的含义就是没确定好,你来了再定那种
在这里插入图片描述
无限定通配是个好东西呀,海纳百川有容乃大。但是注意咯,上面讲过一个大道理,但凡方法调用前必须确定泛型方法类型,集合的add()是啥,那可是泛型方法呀,你调用一个试试?编译不能通过!!!理解这个规定其实也简单,除了上述因为泛型方法的解释之外还可以说你既然泛型最终类型并没有确定,鬼知道你往里面写了啥,不让你写也是正常的
在这里插入图片描述
写不让写,那我读总可以吧。是的没错,你可以读。那这里为什么又可以了呢?集合的get()不也是泛型方法么?年轻了吧,Java中所有类都有一个爹,那就是Object,你读取呗,反正我全部给你返回Object总是没错的,你说对吧
在这里插入图片描述

5.2 上限通配

无限定通配太难顶了,我既要给它自由但是必须限制一下最高权限怎么办?请移步使用上限通配符
在这里插入图片描述
上限通配符还带来一个效果,正常情况下如果使用无限定通配符取数据的时候类型会是上限类型。为什么会这样,你不说泛型擦除后都是Object么?你既然都定义了一个爹,那我把里面的数据类型都向上转型成你爹给出来总是没错的吧,合情合理合法。所以当使用上限通配符后类型擦除将保留上限类型
在这里插入图片描述
你要申请了党组织,出生定义泛型的时候发财一点有几个爹。谁还能阻止孝子认爹的操作不是呀,但是远亲不如近邻。即多个上限时类型擦除后的类型为最左类型
在这里插入图片描述

5.3 下限通配

既然有了上限必然就有下限,具体用法没啥太大区别,就是限制了你最小的类型。这个鬼东西相对于无限定与上限来讲有个特殊的地方,就是可以新增数据。注意新增的类型只能是其自身,很好解释这个问题。要求所有集合元素都必须是该类型父类,那么我增加以后对于哪个父类来讲我都向上转型没问题呀,美滋滋
在这里插入图片描述

六:泛型号外
6.1 八大基本类型

八兄弟就别在泛型里面出没了,毕竟类型擦除后还能说有个Object垫底,但是你这八兄弟明显不能找Object垫底的呀

6.2 泛型数组

类型擦除后一切都是Object,数组也不知道你要干点啥呀。所以针对数组而言是不允许使用确定类型的泛型。当然使用无限定通配符后就不能针对数组中的集合元素执行add()操作,但是如果从集合中取出来集合然后进行类型强转再进行元素新增是允许的操作。编译如果报错类型检查不安全的话加注解@SuppressWarnings(“unchecked”) 搞定,具体怎么操作我就不演示了,不想写出这种无聊的操作。反射也是避开检查的一个好手段
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值