Java工具类—包类我们都知道JDK其实给我们提供了很多Java开发者写好的现成的类,其实都可以理解为工具类。比如我们常见的集合类,日期相关类,数学相关类等等,有了这些工具类,你会发现可以为你节省很多时间,很方便的实现你的需求。当然,没有这些包你也可以实现你的需求,但是你需要时间。今天我们主要学习包装类。一、包装介绍1、为什么需要包装?我们知道Java语言是一种面向对象的编程语言,但是Java中的基本数据类型并不是面向对象的,但是我们在实际使用中往往需要将基本数据类型转化为对象,以便于操作,例如在集合的操作,这时候我们需要将基本类型数据转化为对象,于是出现了一个包装类。2、什么是包装类别?Wrapper类,顾名思义,就是包装什么,就包装什么,显然这里是对基本类型进行包装的类。包装类的作用是将基本类型转化为对象,把基本类型当作对象来对待。在Java中,我们知道有8种基本数据类型,所以也有8种对应的包装类,包装类就是基本类型名的首字母大写。但Integer和Character例外,显示全称,如下表:基本数据类型对应封装类byteByteshortShortintIntegerlongLongfloatFloatdoubleDoublecharCharacterbooleanBoolean2.封装类的继承关系通过阅读Java8官方API文档或查看源码,我们可以知道8个封装类的继承关系如下:通过上面的继承关系图,我们其实可以记住封装类中有6个数字是和Number类相关的,另外两个是不相关的与数字相关的属性默认继承自Object类。通过查看官方API文档,我们也可以了解到这8个包装类都实现了Serializable和Comparable接口。例如下图中的Integer类publicfinalclassIntegerextendsNumberimplementsComparable{}3.包装类的使用方法(基本操作)接下来我讲一下Integer包装类的解释包装类,其他的等等,用法和操作都差不多,只是名字不同而已。1、包装类的构造方法8个包装类都有自己的构造方法,有自己对应的类型参数。其中,除了Character,8个封装类中还有重载的构造方法,参数都是String类型。整数一=新整数(666);整数二=新整数(“666”);2、包装类的自动拆箱在了解自动拆箱之前,我们首先要知道什么是拆箱和装箱。拆包其实主要是处理基本类型和包装类型之间的相互转换。装箱:将原始类型转换为包装器类型的过程称为装箱。拆箱:将包装类型转换为原始类型的过程称为拆箱。其实在JDK1.5版本之前,是没有自动拆箱的,需要开发者手动拆箱://手动拆箱,即将基本类型10转为引用类型Integerinteger=newInteger(10);//或Integerinteger1=Integer.valueOf(10);//手动拆箱,即将引用类型转换为基本类型intnum=integer.intValue();在JDK1.5版本之后,为了减少开发人员的工作,提供了自动装箱和自动拆箱的功能。实现了自动拆箱和自动装箱,如下代码所示://automaticboxingIntegerone=1;//automaticunboxinginttwo=one+10;其实上面两种方式本质上是一样的,只不过一种是自动实现的,一种是手动实现的。至于如何实现自动拆箱,这里不做深入研究。4.封装类的缓存机制。我们先来看看下面的代码。示例1:publicstaticvoidmain(String[]args){Integeri1=100;整数i2=100;整数i3=新整数(100);整数i4=新整数(100);System.out.println(i1==i2);//trueSystem.out.println(i1==i3);//falseSystem.out.println(i3==i4);//falseSystem.out.println(i1.equals(i2));//真System.out.println(i1.equals(i3));//真System.out.println(i3.equals(i4));//true}当我们将值修改为200时,例2:publicstaticvoidmain(String[]args){Integeri1=200;整数i2=200;整数i3=新整数(200);整数i4=新整数(200);System.out.println(i1==i2);//假System.out.println(i1==i3);//假System.out.println(i3==i4);//假System.out.println(i1.equals(i2));//trueSystem.out.println(i1.equals(i3));//trueSystem.out.println(i3.equals(i4));//true}通过上面代码的两端,我们发现修改了值,第五行代码的执行结果发生了变化。为什么?首先,我们需要明确的是,第一行和第二行代码实际上实现了自动装箱的过程,也就是自动实现了Integer.valueOf方法。其次,==比较的是地址,equals比较的是值(这里的eauals改写了,所以比较具体value),所以显然最后五行代码的执行结果是没有疑问的。既然==比较的是地址,为什么例1中的第五行代码为真呢?这就需要我们了解包装类的缓存机制。其实查看Integer类的源码可以发现,在780行有一个privatestatic内部类,如下:privatestaticclassIntegerCache{staticfinalintlow=-128;静态最终int高;静态最终整数缓存[];static{//高值可以由属性配置inth=127;StringintegerCacheHighPropValue=sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");if(integerCacheHighPropValue!=null){try{inti=parseInt(integerCacheHighPropValue);i=Math.max(i,127);//最大数组大小为Integer.MAX_VALUEh=Math.min(i,Integer.MAX_VALUE-(-low)-1);}catch(NumberFormatExceptionnfe){//如果属性无法解析为int,则忽略它。}}高=h;cache=newInteger[(high-low)+1];intj=低;for(intk=0;k=127;}privateIntegerCache(){}}我们知道,静态内部类在整个Integer加载的时候,就已经加载完成了。上面代码初始化了一个Integer类型的数组cache,取值范围为[-128,127]。对于缓存范围内的对象,使用实例化的对象。这样,避免了重复创建多个相同的包装类对象,提高了使用效率。如果我们使用的对象范围在[-128,127]以内,我们就直接去静态区找对应的对象。如果我们使用的对象的范围超出了这个范围,它会帮我们创建一个新的Integer对象。其实下面这就是源码的意思:)];returnnewInteger(i);}所以在例子1的代码中,i1和i2都是100,取值范围是[-128,127],所以在direct区找到静态区,所以指向的地址i1和i2相同,所以i1==i2;例2的代码中,i1和i2都是200,取值范围不是[-128,127],所以新建一个对象放在堆内存中,分别指向不同的地址。所以地址都不同,自然i1不??等于i2。通过分析源码可以发现,只有double和float自动装箱代码没有使用缓存,每次new一个对象都是new,其他6种基本类型都使用了缓存策略。使用缓存策略是因为这些缓存的对象经常使用(例如字符,-128到127之间的数字),防止每次执行自动装箱时都创建对象的实例。5.包装类和基本数据类型的区别。默认值不同。包装类的默认值为null,而基本数据类型的默认值为对应的默认值(例如整数类型的默认值为0,浮点型的默认值为0.0).存储区域不同。基本数据类型是将值保存在栈内存中,而包装类是将对象放在堆中,然后通过对象的引用来调用它们。传输方式不同。基本数据类型变量空间存储值,也传递值。变了,另一个不变,而包装类属于引用数据类型,变量空间存放地址(引用),传递也是引用,一个变了,另一个相应变了。五、小结以上是我个人对Java封装类的理解。其实学习这些工具类还有更好的方法,就是看官方文档(API官方文档地址:https://docs.oracle.com/javas...)最后,最近有很多朋友问我为了一份Linux学习路线图,所以根据自己的经验,利用业余时间熬夜一个月,整理了一本电子书。无论你是面试还是自我提升,相信都会对你有所帮助!免费送给大家,只求大家给我点个赞!电子书|LinuxDevelopmentLearningRoadmap也希望有小伙伴可以加入我的行列,把这本电子书做得更加完美!获得?希望老铁们来个三连击,让更多人看到这篇文章。推荐阅读:干货|程序员和高级架构师免费发送工件的必备资源|支持搜索的资源网站