Java的自动拆装箱以及缓存机制

Java的自动拆装箱以及缓存机制

开发工具与关键技术:idea java
作者:萧氏萧然
撰写时间:2020年8月 5日

了解自动拆装箱之前呢,先得知道什么是基本数据类型以及对应的包装类。
1、基本数据类型
首先我们知道在Java语言提供了八种基本数据类型。六种数字类型(四个整数型,两个浮点型),一种字符类型,还有 一种布尔型。
byte,short, int,long, float, double, char, Boolean

我们在实际开发中,除了使用到数据的值之外,还会涉及到对数据的操作。根据“面向对象”编程的思想,这些常见的操作被抽象成方法,封装到了一个类中,一个基本数据类型对应一个这样的类,这些类统称为“包装类”。
什么是包装类呢?
Java包装类将基本数据类型的值“包装”到对象中,对基本数据类型的操作变为了对对象进行操作,从而使基本值能够包含在为对象保留的操作中

接下来我们来看下它们分别对应的包装类
2、基本数据类型的包装类
Java每个基本类型在java.lang包中都有一个相应的包装类
Byte:对应byte类型 音标:bait
Short:对应short类型 音标:[ʃɔːt]
Integer:对应int类型 音标:[ˈɪntɪdʒər] [ɪnt]
Long:对应long类型 音标:[lɒŋ]
Float:对应float类型 音标:[fləʊt]
Double:对应double类型 音标:[ˈdʌbl]
Character:对应char类型 音标:[ˈkærəktər] [tʃɑːr]
Boolean:对应boolean类型 音标:[ˈbuːliən]
包装类的好处:它提供了一系列操作本类型数据的方法,可以为我们在开发过程中操作8大基本类型数据提供充足的“工具”。

讲完了基本数据类型以及相对应的包装类
敲黑板 接下来的内容就是今天的重点了

3、自动装箱与拆箱

(1) 装箱:
把基本数据类型转换成包装类的过程就是装箱。
(2) 拆箱
反之,把包装类转换成基本数据类型的过程就是拆箱。

(3)自动拆装箱
自动装箱:就是将基本数据类型自动转换成对应的包装类,使它们具有对象的特质,可以调用toString()、hashCode()、getClass()、equals()等方法。
例:Integer a=3;
其实编译器调用的是static Integer valueOf(int i)这个方法,valueOf(int i)返回一个表示指定int值的Integer对象,那么就变成这样:
Integer a=3; => Integer a=Integer.valueOf(3);
  自动拆箱:跟自动装箱的方向相反,将Integer及Double这样的引用类型的对象重新简化为基本类型的数据也就是将包装类自动转换成对应的基本数据类型。

自动拆装箱带来的问题

(4)由于自动拆箱,如果包装类对象为null值,那么自动拆箱时就有可能抛出NPE[null pointer exception]。音标[nʌl ˈpɔɪntər ɪkˈsepʃn] (空指针异常)
(5)如果在一个for循环中有大量拆装箱操作,会浪费很多资源。
(6)包装对象的数值比较,不能简单的使用==,而是需要使用equals比较。
【== 比较的是地址,equals比较的是值】
现在我们来举一个例子
打开Eclipse 音标:[ɪˈklɪps]

那么为什么
Integer A=100;
Integer B=100;
AB为false
Integer C=200;
Integer D=200;
C
D 为false
那么问题来了——都是自动装箱,为什么不同数值自动装箱的结果不一样呢?——这是由于自动拆装箱的缓存机制导+致的。
4、自动拆装箱的缓存机制

//自动装箱
Integer Q=100;

//自定拆箱
int W = Q;
执行自动装箱那句代码的时候,系统为我们执行了:
Integer Q = Integer.valueOf(100);

int W = Q;
执行自定拆箱那句代码的时候,系统为我们执行了:
Int W = Q.intValue();

我们现在就以Integer为例,来分析一下它的源码:
Java.leng.Integer.class 780-852
在这里插入图片描述

可以看得出,当i的值位于[-128,127]的时候,会直接返回Integer缓存数组中相应对象的引用,如果i大于127或小于-128,会重新创建一个Integer实例,并返回。

上面3、(6)说到==是比较内存地址所以当新创建的Integer超过缓存范围就会重新创建实例。所以第一条式子A和B的值都在缓存范围内,因此他们指向同一个对象,因此返回true。C和D的值不在范围内,都是通过new创建出来的,因此不是同一个对象,返回false。
而equals比较的是值
所以 C.equals(D) 返回为true

我们来看看Integer的构造函数:
在这里插入图片描述

它是一个静态的Integer数组对象,也就是说最终valueOf返回的都是一个Integer对象。
所以我们这里可以总结一点:装箱的过程会创建对应的对象,这个会消耗内存,所以装箱的过程会增加内存的消耗,影响性能。

在实际开发过程中,会经常在不经意间就触发了自动拆装箱机制。一套程序跑下来,会生成多少个这样的对象?那开销得多大啊。
因此,出于节省内存和提高性能的目的,从Java5开始,为我们提供了Integer的缓存机制。

再看看自定拆箱
在这里插入图片描述

这个很简单,直接返回value值即可。

拓展内容
1.缓存机制的范围
 Integer缓存数组中默认保存了 -128~127的值的包装类对象。其中后面的127数值可以通过JVM参数 -XX:AutoBoxCacheMax=size(size为填写的大小) 修改【这也是JVM调优的一个常用配置项】。
 注意:调整JVM参数-XX:AutoBoxCacheMax=size,最大缓存值可以达到-128—size,只能调整上限,这和Integer缓存算法实现有关,当然这个参数只对Integer有效,Long…无法调节。

  1. 所有包装类的缓存范围总结
     包装器的缓存:
    Boolean:(全部缓存)
    Byte:(全部缓存)
    Character:(0 — 127缓存)
    Short:(-128 — 127缓存)
    Long:(-128 — 127缓存)
    Integer:(-128 — 127缓存)
    Float:(没有缓存)
    Double:(没有缓存)

Boolean中只有两个对象,要么是true的Boolean,要么是false的Boolean,只要boolean的值相同,Boolean就相等。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值