3分钟带你彻底搞懂Java泛型背后的秘密

3分钟带你彻底搞懂Java泛型背后的秘密作者 的一幕来源 www jianshu

欢迎大家来到IT世界,在知识的湖畔探索吧!

作者:的一幕

来源:www.jianshu.com/p/dd34211f2565

这一节主要讲的内容是java中泛型的应用,通过该篇让大家更好地理解泛型,以及面试中经常说的泛型类型擦除是什么概念,今天就带着这几个问题一起看下:

举一个简单的例子:

3分钟带你彻底搞懂Java泛型背后的秘密



欢迎大家来到IT世界,在知识的湖畔探索吧!

这里可以看出来在代码编写阶段就已经报错了,不能往string类型的集合中添加int类型的数据。

那可不可以往List集合中添加多个类型的数据呢,答案是可以的,其实我们可以把list集合当成普通的类也是没问题的,那么就有下面的代码:

3分钟带你彻底搞懂Java泛型背后的秘密

从这里可以看出来,不定义泛型也是可以往集合中添加数据的,所以说 泛型只是一种类型的规范,在代码编写阶段起一种限制。

下面我们通过例子来介绍泛型背后数据是什么类型

3分钟带你彻底搞懂Java泛型背后的秘密

上面定义了一个泛型的类,然后我们通过反射获取属性和getValue方法返回的数据类型:

3分钟带你彻底搞懂Java泛型背后的秘密

3分钟带你彻底搞懂Java泛型背后的秘密

从日志上看到通过反射获取到的属性是Object类型的,在方法中返回的是string类型,因此咋们可以思考在getValue方法里面实际是做了个强转的动作,将object类型的value强转成string类型。是的,没错,因为泛型只是为了约束我们规范代码,而对于编译完之后的class交给虚拟机后,对于虚拟机它是没有泛型的说法的,所有的泛型在它看来都是object类型,因此泛型擦除是对于虚拟机而言的。

3分钟带你彻底搞懂Java泛型背后的秘密

3分钟带你彻底搞懂Java泛型背后的秘密

比如下面我们没有定义泛型的例子:

3分钟带你彻底搞懂Java泛型背后的秘密

势必在getValue的时候代码有个强转的过程,因此在能用泛型的时候,尽量用泛型来写,而且我认为一个好的架构师,业务的抽取是离不开泛型的定义。

常见的泛型主要有作用在普通类上面,

作用在抽象类、接口、静态或非静态方法上。

类上面的泛型

比如实际项目中,我们经常会遇到服务端返回的接口中都有errMsg、status等公共返回信息,而变动的数据结构是data信息,因此我们可以抽取公共的BaseBean:

3分钟带你彻底搞懂Java泛型背后的秘密

3分钟带你彻底搞懂Java泛型背后的秘密

3分钟带你彻底搞懂Java泛型背后的秘密

<?>通配符

<?>通配符和<T>区别是<?>在你不知道泛型类型的时候,可以用<?>通配符来定义,下面通过一个例子来看看<?>的用处:

3分钟带你彻底搞懂Java泛型背后的秘密

3分钟带你彻底搞懂Java泛型背后的秘密

在定义的时候将Common的泛型指向Common1的泛型,可以看到直接提示有问题,这里可以想,虽然Common1是继承自Common的,但是并不代表BaseBean之间是等量的,在开篇也讲过,如果泛型传入的是什么类型,那么在BaseBean中的getValue返回的类型就是什么,因此可以想两个不同的泛型类肯定是不等价的,但是如果我这里写呢:

3分钟带你彻底搞懂Java泛型背后的秘密

在上面如果定义的泛型是通配符是可以等价的,因为此时的setValue的参数是Object类型,所以能直接将上面定义的泛型赋给通配符的BaseBean。

通配符不能定义在类上面、接口或方法上,只能作用在方法的参数上

3分钟带你彻底搞懂Java泛型背后的秘密

其他的几种情况自己去尝试,正确的使用通配符:

public void setClass(Class<?> class){ //todo } 

欢迎大家来到IT世界,在知识的湖畔探索吧!

<T extends >、<T super >、<? extends >、<? super >
<T extends >表示上限泛型、<T super >表示下限泛型
为了演示这两个通配符的作用,增加了一个类:

3分钟带你彻底搞懂Java泛型背后的秘密

欢迎大家来到IT世界,在知识的湖畔探索吧!//新增加的一个BaseCommon public class Common extends BaseCommon{ } 
3分钟带你彻底搞懂Java泛型背后的秘密

第二个定义的泛型是不合法的,因为BaseCommon是Common的父类,超出了Common的类型范围。

<T super >不能作用在类、接口、方法上,只能通过方法传参来定义泛型
在BaseBean里面定义了个方法:

public void add(Class<? super Common> clazz) { } 
3分钟带你彻底搞懂Java泛型背后的秘密

可以看到当传进去的是Common1.class的时候是不合法的,因为在add方法中需要传入Common父类的字节码对象,而Common1是继承自Common,所以直接不合法。

在实际开发中其实知道什么时候定义什么类型的泛型就ok,在mvp实际案例中泛型用得比较广泛,大家可以根据实际项目来找找泛型的感觉,只是面试的时候需要理解类型擦除是针对谁而言的。

类型擦除

其实在开篇的时候已经通过例子说明了,通过反射绕开泛型的定义,也说明了类中定义的泛型最终是以Object被jvm执行。所有的泛型在jvm中执行的时候,都是以Object对象存在的,加泛型只是为了一种代码的规范,避免了开发过程中再次强转。

泛型信息只存在于代码编译阶段,在进入 JVM 之前,与泛型相关的信息会被擦除掉,专业术语叫做类型擦除。

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://itzsg.com/102136.html

(0)
上一篇 14小时前
下一篇 13小时前

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

联系我们YX

mu99908888

在线咨询: 微信交谈

邮件:itzsgw@126.com

工作时间:时刻准备着!

关注微信