java自动装箱拆箱,开发手册嵩山版

Java开发手册-嵩山版:所有包装类对象之间值的比较,全部用equals方法比较。为什么?

例如:

Integer a=100,b=100,c=200,d=200;
System.out.println(a == b); //true
System.out.println(c == d); //false

先回顾一下==和equals的判断方式

  • == 比较的是两个变量本身的值,即对象在内存中的首地址。—>深
  • equals 比较的字符串中所包含的类容是否相等。—>浅
String s1,s2,s3="abc",s4="abc";
s1 = new String("abc");
s2 = new String("abc");

System.out.println(s1 == s3); //false 两个变量的内存地址不一样
System.out.println(s1 == s2); //false 两个变量的内存地址不一样
System.out.println(s3 == s4); //true 

再来看一下自动装箱和拆箱

(1)自动装箱:把基本类型用它们对应的引用类型包装起来,使它们具有对象的特质,可以调用toString()hashCode()getClass()equals()等方法。

Integer a=3 这是自动装箱

其实编译器调用的是static Integer valueOf(int i)这个方法,valueOf(int i)返回一个表示指定int值的Integer对象,那么就变成这样:

Integer a=3 相等于 Integer a=Integer.valueOf(3)

(2)拆箱:跟自动装箱的方向相反,将Integer及Double这样的引用类型的对象重新简化为基本类型的数据。

int i = new Integer(2) 这是拆箱

编译器内部会调用int intValue()返回该Integer对象的int值

注意: 自动装箱和拆箱是由编译器来完成的,编译器会在编译期根据语法决定是否进行装箱和拆箱动作。

为什么需要自动装箱和拆箱:

节省了常用数值的内存开销和创建对象的开销,提高了效率 。

举例:

public static void main(String[] args) {
    long startTime = System.currentTimeMillis();
    Integer count = 0;
    // int count = 0;
    for (int i = 0; i < 5000000; i++) {
        count += i;
    }
    System.out.println("计算时长:" + (System.currentTimeMillis() - startTime) + " ms");
}

// 执行结果:
// Integer 计算时长:51 ms
// int 计算时长:6 ms

当数值超过127,自动装箱频繁的new对象、分配内存,造成时间和空间上的性能损耗

**解释:**Integer 类中有个方法public static Integer valueOf(int i), 装箱操作

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

在-128至127之间的赋值,Integer对象是在IntegerCache.cache产生的,会复用已有的对象,这个区间的值都可以直接使用 == 进行判断,这个区间外的值就会从新new一个对象,在堆上产生,不会复用已有的对象。

再来看看IntegerCache是什么东西

    /**
     * Cache to support the object identity semantics of autoboxing for values between
     * -128 and 127 (inclusive) as required by JLS.
     *
     * The cache is initialized on first usage.  The size of the cache
     * may be controlled by the {@code -XX:AutoBoxCacheMax=<size>} option.
     * During VM initialization, java.lang.Integer.IntegerCache.high property
     * may be set and saved in the private system properties in the
     * sun.misc.VM class.
     */
    private static class IntegerCache {
        static final int low = -128;
        static final int high;
        static final Integer cache[];
        static {
            // high value may be configured by property
            int h = 127;
            String integerCacheHighPropValue =
                sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
            if (integerCacheHighPropValue != null) {
                try {
                    int i = parseInt(integerCacheHighPropValue);
                    i = Math.max(i, 127);
                    // Maximum array size is Integer.MAX_VALUE
                    h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
                } catch( NumberFormatException nfe) {
                    // If the property cannot be parsed into an int, ignore it.
                }
            }
            high = h;
            cache = new Integer[(high - low) + 1];
            int j = low;
            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() {}
    }

从注释中,我们可以看出,这是个缓存对象,用来提高访问速度。可以使用-XX:AutoBoxCacheMax=<size> 来控制缓存的大小,如果设置 -XX:AutoBoxCacheMax=200。那上面的两个输出就都是true了。

继续学习开发手册发现这里也有装箱拆箱操作:

三目运算符 condition? 表达式 1 : 表达式 2 中,高度注意表达式 1 和 2 在类型对齐时,可能抛出因自动拆箱导致的 NPE 异常。

说明:以下两种场景会触发类型对齐的拆箱操作:

  • 表达式 1 或表达式 2 的值只要有一个是原始类型。
  • 表达式 1 或表达式 2 的值的类型不一致,会强制拆箱升级成表示范围更大的那个类型。
Integer a = 1,b = 2,c = null;
boolean flag =false;
// a*b 的结果是 int 类型,那么 c 会强制拆箱成 int 类型,抛出 NPE 异常
Integer result = (flag ? a*b : c);
System.out.println(result);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值