Java 自动装箱拆箱原理及避坑

简单记录一下自动拆装箱原理以及使用过程中要注意的坑。

目录

1、Java基本数据类型

2、自动拆箱、自动装箱

3、避坑问题


1、Java基本数据类型

基本数据类型和与之对应的包装类型:
boolean、byte、char、float、int、long、short、double
Boolean、Byte、Character、Float、Integer、Long、Short、Double

2、自动拆箱、自动装箱

在JDK1.5之前,进行拆箱和装箱操作时,需要开人员通过代码来实现的,JDK1.5之后,Java出现一个新特性,可以自动对基本数据类型和包装类型进行转换,即:自动拆箱、自动装箱。

2.1 自动装箱

        // 自动装箱 相当于 Integer a = Integer.valueOf(100);
        Integer a = 100;

Integer a = 100; 这个语句,通过deBug可以发现,底层执行了Integer的valueOf()方法,该方法返回了一个Integer对象;

源码:

    public static Integer valueOf(int i) {
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }

2.2 自动拆箱

        Integer b = new Integer(100);
        // 自动拆箱 相当于 int c = b.intValue();
        int c = b;

这个语句,通过deBug可以发现,底层执行了Integer的intValue()方法,该方法返回了一个int基本数据类型;

源码:

    public int intValue() {
        return value;
    }

3、避坑问题

如下代码:

        Integer a = 100;
        Integer b = 100;
        System.out.println(a == b); // 结果:true

        Integer x = 200;
        Integer y = 200;
        System.out.println(x == y); // 结果:false
        System.out.println(x.intValue() == y.intValue()); // 结果:ture

为什么中段代码 Integer x = 200;Integer y = 200; System.out.println(x == y); 执行结果是false呢?

因为Integer x = 200;进行了自动装箱,在自动装箱过程中,底层执行了Integer的valueOf()方法,该方法会判断值的大小,如果在-128至127这个范围,就返回缓存里面的值,否则就会new一个Integer对象。

部分源码:

    // Integer的内部类
    private static class IntegerCache {
        static final int low = -128;
        static final int high;
		// 存放Integer对象
        static final Integer cache[];
        static {
            // high value may be configured by property
            int h = 127;
			// 忽略其他代码.....................
            high = h;
            cache = new Integer[(high - low) + 1];
            int j = low;
			// 忘cache里面存放Integer对象
            for(int k = 0; k < cache.length; k++)
                cache[k] = new Integer(j++);

            // range [-128, 127] must be interned (JLS7 5.1.7)
            assert IntegerCache.high >= 127;
        }
        private IntegerCache() {}
    }
	
	// 判断i的是否在缓存里存在,不存在就创建一个新的对象返回,存在就返回缓存里面的对象
	public static Integer valueOf(int i) {
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }

通过源码可以看出,如果自动装箱值的范围不在缓存内,就重新new一个对象,不同的对象使用==判断自然是为false的,因为内存地址是不一样的;

所以,当我们使用包装类型进行比较的时候,最好使用intValue()方法,如下:

        Integer x = 200;
        Integer y = 200;
        System.out.println(x.intValue() == y.intValue()); // 结果:ture

intValue()方法底层返回的是int基本数据类型,所以可以使用==相比较,当然,包装类型使用equals()方法进行比较也是可以的,Integer的equals方法同样是调用了intValue方法获取int类型值再进行比较,源码:

    // Integer的equals方法
    public boolean equals(Object obj) {
        if (obj instanceof Integer) {
            return value == ((Integer)obj).intValue();
        }
        return false;
    }

不仅仅是int和Integer,其他类型数据也类似,比如看看long和Long的源码,都是同样的原理。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值