Autoboxing and Unboxing——详解Java的自动装箱与拆箱

这篇博客探讨了Java中Integer对象与基础类型int之间的关系,包括自动装箱和拆箱的过程。当Integer值在-128到127之间时,JVM会复用已存在的对象,而超出此范围则每次创建新对象。自动装箱在循环中可能导致大量无用对象的创建,影响性能。此外,Integer对象的比较应使用equals方法而非==。最后,博客提醒开发者注意变量类型声明,避免因自动装箱引发的性能问题。
摘要由CSDN通过智能技术生成

Integer的存储

Integer是int的封装类,一般来说基础变量(int)赋值给Integer对象将自动装箱(Auto Boxing)并为Integer对象分配堆空间。因此即使基础变量值一样,封装类对象指向不同地址。
对JVM为了节省空间, 当Integer的值落在-128~127之间时,如Integer i1 = 2; Integer i2 = 2;此时JVM首先检查是否已存在值为2的Integer对象。如果是,则i2直接是引用已存在对象,即i2 = i1。
事实上, Integer已经默认创建了数值[-128~127]的Integer缓存数据。所以使用Integer i1=2时,JVM会直接在该在对象池找到该值的引用。
对于显式的new Integer(2),JVM将直接分配新空间。
因此,下列判断结果如下:

Integer a = 200;
Integer b = 200;
System.out.println(a==b);       //false
Integer c = 1;
Integer d = 1;
Integer e = new Integer(1);
System.out.println(c==d);       //true
System.out.println(d==e);       //false;

int i = 1;如果在类中定义,就存放在堆,在方法中定义,就存放在栈(直接存放i=1)
在这里插入图片描述

自动拆箱与装箱

Integer、Long、Double这些包装类是final修饰的,不能被继承。Integer对象是不可变的,函数传递参数时,在函数内部修改,不会影响外部。
ArrayList(底层是object数组),需要传入对象,而不能直接传入int,所以有了Integer包装类,而在list.add(3)时,会自动装箱成为Integer。int n = list.get(i)会自动拆箱。
Integer.valueOf()底层就是new Integer(num),判断两个int可以用==,但判断两个Integer不能用==,需要用equals,就算是Integer a = new Integer(1); Integer b = new Integer(1); a==b

也会输出false;Integer i1 = 2; Integer i2 = 2;i1==i2会输出true。
自动装箱的弊端
自动装箱有一个问题,那就是在一个循环中进行自动装箱操作的情况,如下面的例子就会创建多余的对象,影响程序的性能。

Integer sum = 0;
for(int i=1000; i<5000; i++){
   sum+=i;
}

上面的代码sum+=i可以看成sum = sum + i,但是+这个操作符不适用于Integer对象,首先sum进行自动拆箱操作,进行数值相加操作,最后发生自动装箱操作转换成Integer对象。其内部变化如下
1
2 sum = sum.intValue() + i;
Integer sum = new Integer(result);
由于我们这里声明的sum为Integer类型,在上面的循环中会创建将近4000个无用的Integer对象,在这样庞大的循环中,会降低程序的性能并且加重了垃圾回收的工作量。因此在我们编程时,需要注意到这一点,正确地声明变量类型,避免因为自动装箱引起的性能问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值