【学习Day11】什么是自动装箱和自动拆箱,什么时候下应该避免自动拆装箱?

目录
- 一、什么是自动拆箱和自动装箱?
- 二、常见的自动拆装箱操作类型?
- 三、基本数据类型和封装类的区别?
- 四、基本数据类型和封装类优缺点?
- 4.1、基础数据类型
- 4.2、封装类
- 五、基本数据类型和封装类适用场景
- 六、可能出现的问题以及什么时候避免自动拆装箱
- 七、总结
- 后续
- 八、Integer 与128的故事
- 完结
一、什么是自动拆箱和自动装箱?
装箱:
装箱操作就是把基础数据类型自动转换成引用类型,比如定义一个数值类型
Integer num = 1它自动把int类型的数字转换为对应的引用类型,这就是装箱操作。
拆箱:
拆箱操作就是把引用类型转换为对应的基础类型,比如Integer num = 20这个num变量赋值给int sumber = num这就是拆箱操作。
二、常见的自动拆装箱操作类型?
| 装箱类型 | 拆箱类型 |
|---|---|
| Integer | int |
| Char | char |
| Float | float |
| Double | double |
| Long | long |
| Short | short |
| Byte | byte |
| Boolean | boolean |
以上就是自动拆装箱对应的类型,拆装箱操作针对于Java的八种基本数据类型,基本数据类型就是拆箱类型,而装箱类型就是引用类型也成为封装类。
三、基本数据类型和封装类的区别?
| 类型 | 基础数据类型 | 包装类 |
|---|---|---|
| 默认值不同 | 字符串为‘’ 数字为0 | null |
| 存储位置 | 栈 | 堆 |
| 传递数据 | 值传递 | 引用传递 |
| 创建变量 | 直接给变量赋值 | 创建对象在赋值 |
| 比较 | == | equals |
数据传递分为值传递和引用传递,他们的区别就是在使用的过程值传递直接使用这个的对象的值,而引用传递传递的是存在在堆中的内存地址,在根据这个内存地址去拿到对应的值。
四、基本数据类型和封装类优缺点?
4.1、基础数据类型
优点:
- 读取速度快(因为存储在栈中)
- 没有拆箱操作,提高性能
缺点:
- 功能少,只能做简单的操作
4.2、封装类
优点:
- 由于是对象,它有丰富的方法,可以做复杂的功能
- 封装得到好处,在于隐藏实现的得到细节,更安全
缺点:
- 读取速度会比基础数据类型快(因为存储在堆中,以及要进行拆箱操作)
五、基本数据类型和封装类适用场景
基础数据类型:
操作简单的场景,比如一个类需要两个int类型的变量来做一个sum的操作,就可以使用基础数据类型,在比如用一个boolean类型的一个变量做一个判断就完全可以用基础数据类型,用引用类型也没问题,但是没必要,那样只会浪费资源。
封装类:
复杂操作的场景,以及值有可能为Null的情况。
- 场景1:比如定义一个Integer类型的变量,用它作为一个方法的返回值,这个方法经过一些列的操作,最后得到一个Integer类型的数据,我们并不知道它最后返回一个什么东西,有可能是数字,也有可能啥也没有,如果用int类型来接收Null,就出出现空指针异常,这时候就得用包装类来接收。
- 场景2:在比如我想要得到Integer这个类型的最大值,这时用基础类型是不行的因为它没有任何的方法,它只能存储数据,就得用封装类调用Integer.MAX_VALUE来实现。
六、可能出现的问题以及什么时候避免自动拆装箱
以上简单的了解了自动拆装箱是什么,它们有什么区别,那么现在来了解一下在自动拆装箱的时候会出现什么问题
问题1: NullPointerException异常,上面场景下提到了,在一系列操作过后,有可能会出现Null这中情况一定要用封装类,不可让他自动拆箱
问题2: 通过以上它们的区别可知,在比较数值的时候有所不同, == 和 equals都可以比较值,但是它们又不同的地方,==只能比较-128 到 127 之间的数字,超出这个范围就要用equals,原因后续补充
问题3: 比如在一个循环中定义一个int类型,而在下面调用其他方法返回值为Integer 把这个值赋给int这个拆箱操作就会很浪费资源,在这种情况最好保持类型一致。
七、总结
根据以上内容分析,基础数据类型和封装类都有各自的好处,根据实际的需要来选择,需要注意的是自动拆装箱NPM异常的问题,在使用的过程中要谨慎。
后续
八、Integer 与128的故事
上面已说明基础类型和封装类的区别,其中有一条在比较值的时候不同,下面就来详细说说他们的不同
-
为什么Integer a = 128, Integer b = 128 用双等比较不相等?

为什么用==比较127的时候返回true,128就返回false了呢?这里面有一个大大大大得到坑。原因是Integer自在的缓存模式惹的祸,定义Integer类型它自动进行了装箱操作,通过Integer的valueOf方法实现,让我们来看看源码

在我们通过Integer a = 1的时候它自动通过valueOf(int i)这个方法来实现,而这个方法里面有IntegerCache的字样,问题就出在这里,让我们来看看,首先它做了一个判断,其中有两个属性low和high,这个两个东西是啥 继续来看

那两个属性是IntegerCache静态类中的两个属性,并且第一个是-128,high它的值是在静态代码块中赋的默认给了127,啊那就知道了那个判断的意思了就是我们赋值的时候如果值在-128到127之间他就会放在缓存里面,如果超过这个范围就会重新new Integer(),new出来的东西肯定是堆里面了。看到这里就知道为啥128不相等,-128到127之间的值都是在一个地方,而超过范围它是两个对象了啊,那肯定不相等啊。这就是原因 -
为什么会有Integer缓存
因为我们常见的基本数据类型中,使用包装类包装数值时会创建大量对象,如果没有缓存的话,会有大量的包装类被创建,占用内存,降低效率。选择最常用的数值范围设置缓存机制,就可以优化这一现象。
- 自定义缓存的大小
只可以设置最大值,不可以设置最小值,在运行的时候添加一下参数
-XX:AutoBoxCacheMax=最大值

其运行结果

- 其他数据类型缓存

来源 https://blog.csdn.net/LNF568611/article/details/123599649
完结
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
