【Integer】| 深度剥析包装类缓存原理Ⅶ

这篇具有很好参考价值的文章主要介绍了【Integer】| 深度剥析包装类缓存原理Ⅶ。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一. 🦁 前言

整型、char类型所对应的包装类,在自动装箱时,对于-128~127之间的值会进行缓存处理,其目的是提高效率。
缓存处理的原理为:如果数据在-128~127这个区间,那么在类加载时就已经为该区间的每个数值创建了对象,并将这256个对象存放到一个名为cache的数组中。每当自动装箱过程发生时(或者手动调用valueOf()时),就会先判断数据是否在该区间,如果在则直接获取数组中对应的包装类对象的引用,如果不在该区间,则会通过new调用包装类的构造方法来创建对象。

二. 🦁 源码分析

1. valueOf(int i)

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

通过源码我们可知道,当参数i不在[IntegerCache.low , IntegerCache.high]范围内时,就直接实例化一个Integer对象并返回;否则返回IntegerCache类里面的cache数组里面的数据。
那么到这里,我们就能根据语义想得到了,Integer自动拆箱的缓存工作是由IntegerCache类完成的,咱们来点击查看一下这个类的工作原理。

2. IntegerCache类

我们查看这个类时,发现这个类是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 {@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
     * jdk.internal.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 =
                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() {}
    }

这个静态内部类包含了三个变量:low,high,cache[]数组。

  1. 在静态代码块中,先通过VM.getSavedProperty()来获取high的值,检查"integerCacheHighPropValue"变量是否不为空,如果不为空,它尝试使用parseInt()方法将其解析为整数。如果解析成功,它将"i"的值设置为解析后的整数,并将其与127取最大值。然后它计算"h"变量的最大值,即"i"和Integer.MAX_VALUE减去负的"low"值再减1之间的较小值
    如果未设置属性值或无法将其解析为整数,则代码会优雅地忽略该属性,并继续使用默认值 127。

tips:
在Java中,系统属性是提供有关Java虚拟机(JVM)和运行环境配置信息的键值对。可以使用 System.getProperty() 方法访问它们。VM.getSavedProperty()则是类似于 System.getProperty() 方法,可以获取java.lang.Integer.IntegerCache.high的属性值

  1. 实例化cache数组的大小为 256,并且循环赋范围为[-128,127]的值进数组中。最后检查是否缓存全部的值(assert IntegerCache.high >= 127)。
  2. 最后构造私有的构造方法,以防止外部的类访问到IntegerCache。

三. 🦁 总结

Integer是Java语言中的一种基本数据类型,用来表示整数值。其原理是采用二进制补码表示法,即将整数的绝对值转化为二进制数,然后在最高位上添加一个符号位(0表示正数,1表示负数),并将二进制数按位取反,再加上1,得到补码。

例如,十进制数5的二进制表示为101,加上符号位后为0101,取反得到1010,加上1后得到1011,这就是5的补码表示。同理,-5的补码表示为1101。

在计算机内部,整数的加减乘除运算都是在二进制补码的基础上进行的。加法运算时,先将两个数的补码相加,然后对结果进行溢出检查;减法运算时,将被减数的补码取反后再加上减数的补码,即转化为加法运算;乘法运算和除法运算也是在二进制补码的基础上进行的。

总之,Integer数据类型的原理就是采取二进制补码表示法,使得整数的加减乘除运算都能在计算机内部高效地进行。

这一期的Java基础复习到这里,咱们下一期见!!!文章来源地址https://www.toymoban.com/news/detail-498071.html

到了这里,关于【Integer】| 深度剥析包装类缓存原理Ⅶ的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【ArrayList】| 深度剥析Java SE 源码合集Ⅵ

    ArrayList ,基于 [] 数组实现的,支持 自动扩容 的动态数组。相比数组来说,因为其支持 自动扩容 的特性,成为我们日常开发中,最常用的集合类,没有之一。 ArrayList 实现的接口、继承的抽象类,如下图所示: 实现了 4 个接口,分别是: java.util.List 接口,提供数组的添加、

    2024年02月04日
    浏览(41)
  • 【LinkedHashMap】| 深度剥析Java SE 源码合集Ⅴ

    众所周知,HashMap 提供的访问,是 无序 的。而在一些业务场景下,我们希望能够提供 有序 访问的 HashMap 。那么此时,我们就有两种选择: TreeMap :按照 key 的顺序。 LinkedHashMap :按照 key 的插入和访问的顺序。 LinkedHashMap ,在 HashMap 的基础之上,提供了 顺序 访问的特性。而

    2023年04月19日
    浏览(38)
  • 【TreeSet】| 深度剥析Java SE 源码合集Ⅳ

    TreeSet是基于红黑树实现的Set集合,它具有以下特点: 有序性:TreeSet是有序的,它按照元素的自然排序进行排序,或者按照指定的Comparator进行排序。 不允许重复元素:与HashSet一样,TreeSet也不允许重复元素,如果试图将一个已经存在的元素添加到TreeSet中,那么添加操作将会

    2023年04月17日
    浏览(41)
  • 【SpringBoot源码剥析】| 项目运行原理

    Spring Boot 提供了 Maven 插件

    2023年04月10日
    浏览(26)
  • 【HashMap】| 深度剥析Java SE 源码合集Ⅱ | 你会吗?

    HashMap 是 Map 接口的接口实现类,它采用哈希算法实现,是 Map 接口最常用的实现类。 由于底层采用了哈希表存储数据,所以要求键不能重复,如果发生重复,新的值会替换旧的值。 HashMap 在 查找、删除、修改方面都有非常高的效率 。 HashMap 底层实现采用了哈希表,既集合了

    2024年01月22日
    浏览(27)
  • 【SpringMVC】| SpringMVC执行流程原理 | 常用注解 剥析

    MVC全称Model View Controller,是一种设计创建Web应用程序的模式。这三个单词分别代表Web应用程序的三个部分: Model (模型):指数据模型。用于存储数据以及处理用户请求的业务逻辑。在Web应用中,JavaBean对象,业务模型等都属于Model。 View (视图):用于展示模型中的数据的

    2024年02月06日
    浏览(27)
  • == 和 equles()基于字符串、基本数据类型、包装类应用的不同和原理

    对于 == 和 equals() 大家都很熟悉,大多也知道结论,但是运用的时候,有时候根据结论来,完全是摸不着头脑,所以我在这系统的简述一下关于两者在基本数据类型、字符串类型、包装类这三个应用上的区别。 下面我主要是说 == 的运用,因为equals()对于字符串就是比较内容,

    2024年03月19日
    浏览(50)
  • 【SpringBoot源码剥析】| 依赖管理

    我们创建项目时添加的依赖并没有帮我们指定版本号 version ,那SpringBoot是如何来指定版本账号的呢? 现在我们来剥析一下SpringBoot的父依赖启动器 spring-

    2024年02月04日
    浏览(35)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包