Java 自动装箱与拆箱

我们知道,Java中基本数据类型及其对应的包装器类型如下:

基本数据类型大小包装器类型
byte8bitByte
char16bitCharacter
short16bitShort
int32bitInteger
long64bitLong
float32bitFloat
double64bitDouble
boolean/Boolean
自动装箱与拆箱

那什么是自动装箱和拆箱呢?

简单来说,自动装箱其实就是自动将数据类型转成包装器类型,自动拆箱就是自动将包装器类型转成基本数据类型。

Integer x = 127;//装箱,调用了Integer.valueOf(127)来完成装箱操作
int y = x; //拆箱,调用了Integer.intValue()来自动完成拆箱操作

装箱过程就是调用包装器的valueOf(xxx)方法来实现的,拆箱就是调用包装器的xxxValue()方法来实现的。

Integer的valueOf()方法以及Integer缓存池实现如下:
在这里插入图片描述
在这里插入图片描述

如果数值i的范围在Integer缓存池取值范围内,就返回IntegerCache.cache中已经存在的对象的引用;否则创建一个新的Integer对象。Integer缓存池的默认范围是[-128, 127],这个上限是可以设置的。

其他基本数据类型和对应的包装器类型,可以同样去看它们的valueOf()方法实现,可以发现:Integer、Short、Byte、Character、Long这几个类的valueOf方法的实现是类似的;Double、Float的valueOf方法的实现是类似的,没有涉及缓存池,每次调用返回的都是不同的对象引用。
在这里插入图片描述

相关面试题

面试中,我们可能会遇到这么一道题:
以下代码的输出结果是:

public class Main {
    public static void main(String[] args) {
        Integer x1 = 127;
        Integer x2 = 127;
        Integer x3 = 128;
        Integer x4 = 128;
        int x5 = 128;
        int x6 = 128;
        Double d1 = 127.00;
        Double d2 = 127.00;
        Character c1 = 'a';
        Character c2 = 'a';
        Boolean b1 = true;
        Boolean b2 = true;
        System.out.println(x1 == x2);//true, 127在Integer的缓存池范围内,多次调用取得的是同一对象的引用
        System.out.println(x3 == x4);//false, 128不在Integer的缓存池范围内,多次调用取得的是不同对象的引用
        System.out.println(x5 == x6);//true, 比较的是基本数据类型的值
        System.out.println(x4 == x5);//true,
        System.out.println(d1 == d2);//false, 每次调用Double.valueOf(double d) 都会new一个对象来返回
        System.out.println(c1 == c2);//true
        System.out.println(b1 == b2);//true
    }
}

在这里插入图片描述

相信这个结果就很好理解了。

需要注意的是:

  • 当 "=="运算符的两个操作数都是包装器类型的引用,则是比较指向的是否是同一个对象,而如果其中有一个操作数是表达式(即包含算术运算)则比较的是数值(即会触发自动拆箱的过程)。

  • equals参数为包装类型,则先比较是否为同类型,非同类型直接返回false,同类型再比较值
    在这里插入图片描述

  • ==VS equals()

    • ==判断两个对象是不是同一个对象(基本数据类型用 == 比较的是值,引用数据类型用 == 比较的是内存地址)
    • euqals()在没有重写的情况下,相当于通过==比较两个对象;重写的情况下,一般是通过重写equals()来判断两个对象的内容是否相等,相等就返回true(也就是说认为这两个对象相等)。
补充:String Pool

在这里插入图片描述
字符串常量池(String Pool)保存着所有字符串字⾯量(literal strings),这些字⾯量在编译时期就确定。不仅如此,还可以使用 String 的 intern() 方法在运行过程将字符串添加到 String Pool 中。

当一个字符串调用 intern() 方法时,如果 String Pool 中已经存在⼀个字符串和该字符串值相等(使用equals() 方法进行确定),那么就会返回 String Pool 中字符串的引用;否则,就会在 String Pool 中添加一个新的字符串,并返回这个新字符串的引用。

当使用new关键字创建字符串对象时,String s1 = new String("aaa");会创建两个字符串对象(前提是 String Pool 中还没有 “abc” 字符串对象):“abc” 属于字符串字面量,因此编译时期会在 String Pool 中创建⼀个字符串对象,指向这个 "abc"字符串字面量;使用new的方式会在堆中创建⼀个字符串对象。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值