Java中关于自动拆装箱

java学习 专栏收录该内容
10 篇文章 0 订阅

首先我们要了解基本数据类型与包装类型。

包装类型

​ Java 语言是一个面向对象的语言,但是 Java 中的基本数据类型却是不面向对象的,这在实际使用时存在很多的不便,为了解决这个不足,在设计类时为每个基本数据类型设计了一个对应的类进行代表,这样八个和基本数据类型对应的类统称为包装类(Wrapper Class)。

​ 包装类均位于 java.lang 包,包装类和基本数据类型的对应关系如下表所示

基本数据类型包装类
byteByte
booleanBoolean
shortShort
charCharacter
intInteger
longLong
floatFloat
doubleDouble

​ 在这八个类名中,除了 Integer 和 Character 类以后,其它六个类的类名和基本数据类型一致,只是类名的第一个字母大写即可。

扩展:为什么需要包装类?

	因为java是一门面向对象的语言,在许多地方使用的是对象而不是基本数据类型,这时候就需要使用包装类了。例如,在集合类中,默认要求的是Object,无法将基本数据类型放入。

自动拆箱与装箱

​ 这里的拆箱与装箱其实都是指的基本数据类型与包装类的转换,例如以int类型为例:

//装箱:
Integer i = new Integer(1);

//拆箱:
int j = i.intValue();

​ 在 Java SE5 之前 ,都需要手动对数据转换进行装箱与拆箱,但是在Java SE5 之后,Java提供了自动装箱与拆箱。

​ 上面代码可以简化成这样:

Integer i = 1;

int j = i;

​ 在经过反编译后,有:

Integer i = Integer.valueOf(1);

int j = i.intValue();

​ 从上面反编译后的代码可以看出,int 的自动装箱都是通过 Integer.valueOf() 方法来实现的,Integer 的自动拆箱都是通过 i.intValue` 来实现的。

​ 在试验过其他类型后,发现其他类型也是通XXX.valueOf()方法实现自动装箱,使用XXXValue()方法来实现拆箱。

自动装拆箱常见场景

​ 1. 将基本类型放入集合类中

List<Integer> list = new ArrayList<>();
int i = 1;
list.add(i);

​ 反编译后:

List<Integer> list = new ArrayList<>();
int i = 1;
list.add(Integer.ValueOf(i));

​ 2. 包装类型与基本类型比较

Boolean flag = false;
System.out.println(flag ? "阿云""阿戴");

​ 反编译后:

Boolean flag = false;
System.out.println(flag.booleanValue() ? "阿云""阿戴");

​ 3. 包装类型的运算

int a = 1;
Integer b = 2;
System.out.println(a + b);

​ 反编译后:

int a = 1;
Integer b = 2;
System.out.println(a + b.intValue());

​ 4. 三目运算符中

int a = 1;
Integer b = 2;
System.out.println(a > 0 : a : b);

​ 反编译后:

int a = 1;
Integer b = 2;
System.out.println(a > 0 : a : b.intValue());

在三目运算符中,如果后面结果为基本类型和对象时,将会对对象进行自动拆箱,如果此时对象为null,则会报出空指针异常。

自动拆装箱与缓存

Integer integer1 = 3;
Integer integer2 = 3;

if (integer1 == integer2)
    System.out.println("integer1 == integer2");
else
    System.out.println("integer1 != integer2");

Integer integer3 = 300;
Integer integer4 = 300;

if (integer3 == integer4)
    System.out.println("integer3 == integer4");
else
    System.out.println("integer3 != integer4");

​ 按理来说上面的两个判断的结果都是 false。虽然比较的值是相等的,但是由于比较的是对象,而对象的引用不一样,所以会认为两个 if 判断都是 false 的。在 Java 中,== 比较的是对象引用,而 equals 比较的是值。所以,在这个例子中,不同的对象有不同的引用,所以在进行比较的时候都将返回 false。但其实,最后结果与想象有些小出入。

​ 输出结果

integer1 == integer2
integer3 != integer4

​ 原因就和 Integer 中的缓存机制有关。在 Java 5 中,在 Integer 的操作上引入了一个新功能来节省内存和提高性能。整型对象通过使用相同的对象引用实现了缓存和重用。

  • 适用于整数值区间-128 至 +127。

  • 只适用于自动装箱。使用构造函数创建对象不适用。

如果一个变量p的值是:

-128至127之间的整数(§3.10.1)

true 和 false的布尔值 (§3.10.3)

‘\u0000’至 ‘\u007f’之间的字符(§3.10.4)

中时,将p包装成a和b两个对象时,可以直接使用a==b判断a和b的值是否相等。

自动拆装箱的缺点

  • ​ 包装对象的比较不能简单通过==,视情况使用equals
  • ​ 包装对象如果为null,自动拆装箱会报出控制住异常
  • ​ 如果在循环中存在拆装箱操作,将会浪费大量资源
  • 0
    点赞
  • 0
    评论
  • 0
    收藏
  • 打赏
    打赏
  • 扫一扫,分享海报

©️2022 CSDN 皮肤主题:技术工厂 设计师:CSDN官方博客 返回首页

打赏作者

承与

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值