由自动装箱和拆箱引发我看Integer源码

发布时间:2020-07-07 20:19:25 作者:张涛泽
来源:网络 阅读:295

背景和问题

  在看别人整理的资料时,看到如下一段代码:

由自动装箱和拆箱引发我看Integer源码

package com.sitech.test;/**
 * 自动装箱和拆箱 jdk1.6
 * @author liaowp
 * */public class TestInteger {    public static void main(String[] args) {
        Integer i1 = 80, i2 = 80, i3 = 999, i4 = 999;
        System.out.println(i1 == i2);//true
        System.out.println(i3 == i4);//false    }
}

由自动装箱和拆箱引发我看Integer源码

  如果没有看过源码的同学肯定觉的答案要么是2个true要么是2个false。我刚看到这一段代码的时候也觉的是2个true,感觉自己100%确定,不过真正运行之后才发现傻眼了,一个true一个false,这是Bug吧。其实LZ以前看过一部分Integer源码了,但是现在想想好像看的不认真,尴尬了。于是被这个问题触发了LZ要认真看一次Integer源码了(我要认真了,哈哈)。

  我们还是回到上面那个问题吧,先把问题解决了在吹nb。我们可以看到上面的代码4个变量都是Integer的引用,所以输出的==运算比较的不是Integer值而是Integer引用。装箱的本质是什么呢?当我们给一个Integer对象赋一个int值的时候,会调用Integer类的静态方法valueOf,我们看一看valueOf方法就知道为什么会有这样的结果了。

由自动装箱和拆箱引发我看Integer源码

    /**
     * Returns an {@code Integer} instance representing the specified
     * {@code int} value.  If a new {@code Integer} instance is not
     * required, this method should generally be used in preference to
     * the constructor {@link #Integer(int)}, as this method is likely
     * to yield significantly better space and time performance by
     * caching frequently requested values.
     *
     * This method will always cache values in the range -128 to 127,
     * inclusive, and may cache other values outside of this range.
     *
     * @param  i an {@code int} value.
     * @return an {@code Integer} instance representing {@code i}.
     * @since  1.5     */
    public static Integer valueOf(int i) {//是一个静态方法 IntegerCache是一个内部类        assert IntegerCache.high >= 127;//断言  参考http://lavasoft.blog.51cto.com/62575/43735/        if (i >= IntegerCache.low && i <= IntegerCache.high)//如果i大于对于IntegerCache.low()且i小于等于IntegerCache.high            return IntegerCache.cache[i + (-IntegerCache.low)];//直接从缓存取出来        return new Integer(i);//新创建一个Integer对象
    }

由自动装箱和拆箱引发我看Integer源码

  从上面的代码中我们可以看出Integer维持了一个缓存系统,如果在缓存的范围内直接取出来就好了,雅思培训机构如果不在的就要创建新的Integer对象。但是具体缓存范围是什么的,我们在深入进去看看:

由自动装箱和拆箱引发我看Integer源码

    /**
     * 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 -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;//最小值是-128        static final int high;//最高        static final Integer cache[];//缓存数组  这三个都final,不可修改的        static {//静态代码块   静态代码块会比改造方法先执行            // high value may be configured by property
            int h = 127;//默认的
            String integerCacheHighPropValue =//定义一个String 
                sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");//取得设置的值            if (integerCacheHighPropValue != null) {//如果设置了就用设置的值                int i = parseInt(integerCacheHighPropValue);//把String转换为int
                i = Math.max(i, 127);//获得i和127的更大的一个,其实是不能小与默认的                // Maximum array size is Integer.MAX_VALUE
                h = Math.min(i, Integer.MAX_VALUE - (-low));//如果取的小的那个,不能超过Integer的最大值+low
            }
            high = h;//最大值为127

            cache = new Integer[(high - low) + 1];//创建缓存数组大小            int j = low;//最小值            for(int k = 0; k < cache.length; k++)
                cache[k] = new Integer(j++);//缓存初始化
        }        private IntegerCache() {}//私有构造
    }

由自动装箱和拆箱引发我看Integer源码

问题解决

由自动装箱和拆箱引发我看Integer源码

Integer的缓存

  看完之后我相信基本都知道为啥一开始的那一段代码会这样了,我现在做一个小的总结,Integer里面有一个内部类IntegerCache,是用来做缓存优化性能的。默认缓存了-128到127中间的数字,据说这些使的比较频繁。其实java里面好多的类都有这样的优化。如果在-128-127之间的就直接拿缓存的,不在的就new一个Integer所以这也就解释了上面的那个问题了嘛


推荐阅读:
  1. java中的自动装箱和拆箱是什么
  2. java的自动装箱和自动拆箱是什么

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

package public false

上一篇:oracle在组合索引上,只使用部分列进行查询(查询时必须包含前导列,否则会走全表扫描)

下一篇:设置导航栏颜色和字体颜色

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》