【疑问解决】在自动装箱中Integer赋予一个常量1,为什么会出现==判断true和flase的情况(JDK源码、内部缓冲)

news2024/11/19 6:13:24

问题来源自讲课时的Integer练习中

当时第一反应是false        true        true

因为第一段的输出为flase毋庸置疑了,因为已经new了两个新的堆空间,当然指向不同的空间了

但是第二段第三段就没有头绪了,自动装箱了难道不是执行同一个空间吗 。

实际上要看自动装箱时的隐式调用Integer.valueOf的源代码

解答:

        输出为false true true

        第一段是对的,但第二端隐式调用了Integer的valueOf方法,使用debug可以追入

1.if语句内的low和high值

        进入该方法后,可以看到有if语句分别判断执行两个return,先看if里面的

if (i >= IntegerCache.low && i <= IntegerCache.high)

        这一句话里面的IntegerCache.low和.high是谁呢?接着追入可以发现

        这个low和high在本类开头已经声明了,而且是静态的,在类加载的时候就已经赋值完毕了,low=-128。

         这段源码重要的是看if语句有没有执行,而在这个if语句块内,执行的是判断有没有在虚拟机初始化时设置初始值,如果没有设置初始值,将默认为空,因为getSavedProperty方法返回java.lang.String为空

String integerCacheHighPropValue =
                sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");

         调用虚拟机的获取设置,编译时不输入就为空

public static java.lang.String getSavedProperty(java.lang.String s) { /* compiled code */ }

         为空不执行if语句high被赋予默认值127,所以min = -128,high = 127

2.if块内return的东西

        到目前为止,我们解决了if判断是从-128 && 127的值(127可以通过jvm设置)

        接下来探讨return后面的一串是什么东西

        首先是cache,我们可以发现格式是一个数组,使用查找可以找到在本来开头定义了一个对象数组

        注意,这里的对象是static的,所以在类加载的时候编创建好了,我们再找找该静态对象在哪里被赋值或者创建

        查找可以发现,cache数组对象在类被调用时创建了个大小为127+128+1大小的数组,通过for循环赋值从j++也就是-128 ++直到255,这时的k循环从0~255,数值大小循环为-128到127。

         随后if语句块内的就很好理解了,cache已经是静态对象而且被创建好了,直接返回对应的数值的数组对象下标回去即可,这一个机制也叫JDK的内部缓冲

        

3.if语句块外的

        这个就没什么好解释的了,在-128到127范围之外的我简单粗暴的new一个int i 的值的对象返回给你就行了

更多关于该JDK内部缓冲的分析请参考

OpenJDK源码研究笔记(五)-缓存Integer等类型的频繁使用的数据和对象,大幅度提升性能(一道经典的Java笔试题)_51CTO博客_openjdk使用

总结

        因为题目的第二段我们赋的值是int常量,使用自动装箱隐式调用valueOf方法,在该方法内if判断为真,返回静态对象cache[129] = Interger(1)回去,所以此时的m指向Interger(1)对象,然后第二句同理,n也指向Interger(1)对象,所以sout(m == n)打印为true

        然后第三段,前面的都同理,但x和y都不在-128~127内在if判断时为假,直接new一个新空间,所以x和y当然执行两个不同的新空间,所以==为false

        所以正确答案为 false true flase,完毕

题目代码

/**
 * @author 银海
 * @version 1.0
 */
public class WrapperExercise02 {
    public static void main(String[] args) {
        Integer i = new Integer(2);
        Integer j = new Integer(1);
        System.out.println(i == j);  //False
        //所以,这里主要是看范围 -128 ~ 127 就是直接返回
        /*
        老韩解读
        //1. 如果i 在 IntegerCache.low(-128)~IntegerCache.high(127),就直接从数组返回
        //2. 如果不在 -128~127,就直接 new Integer(i)
         public static Integer valueOf(int i) {
            if (i >= IntegerCache.low && i <= IntegerCache.high)
                return IntegerCache.cache[i + (-IntegerCache.low)];
            return new Integer(i);
        }
         */
        Integer m = 1; //底层 Integer.valueOf(1); -> 阅读源码
        Integer n = 1;//底层 Integer.valueOf(1);
        System.out.println(m == n); //T
        //所以,这里主要是看范围 -128 ~ 127 就是直接返回
        //,否则,就new Integer(xx);
        Integer x = 128;//底层Integer.valueOf(1);
        Integer y = 128;//底层Integer.valueOf(1);
        System.out.println(x == y);//False

    }
}

JDK源码有关源码

     /**
     * 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++);
    
    /**
     * 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) {
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }
    /**
     * The value of the {@code Integer}.
     *
     * @serial
     */
    private final int value;

    /**
     * Constructs a newly allocated {@code Integer} object that
     * represents the specified {@code int} value.
     *
     * @param   value   the value to be represented by the
     *                  {@code Integer} object.
     */
    public Integer(int value) {
        this.value = value;
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1141873.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Go结构体接口反射

文章目录 Go结构体&接口&并发&反射一、结构体struct0、Type关键字1、struct定义及使用2、struct tag3、struct匿名成员3、struct继承4、struct方法 二、接口interface1、接口定义和使用2、空接口3、接口多态及嵌套 三、Go并发1、go协程2、chan管道3、单向管道4、Se…

oracle19c配置驱动

1.遇到的问题 下载jar包 https://www.oracle.com/database/technologies/appdev/jdbc-ucp-19c-downloads.html 执行命令 mvn install:install-file -DgroupIdcom.oracle -DartifactIdojdbc19 -Dversion19.3.0.0 -Dpackagingjar -Dfileojdbc8.jar2.配置驱动 # 数据源配置 data…

浅析体育馆智能信息化升级的四大痛点与解决方案

体育馆是举办重要体育赛事、文艺汇演、商业演出等活动的重要场所&#xff0c;除了日常锻炼的人们以外&#xff0c;一旦举行活动都是人满为患。随着人们日益提高的体育需求&#xff0c;传统体育馆的设施已经无法满足大众的要求&#xff0c;为此旭帆科技特根据传统体育馆存在的几…

适合小团队的任务管理软件有哪些?5款小团队使用最多的项目工具

众所周知&#xff0c;在团队管理中&#xff0c;通过使用适当的任务管理软件&#xff0c;团队可以更高效地组织、分配和跟踪任务&#xff0c;提高工作效率和团队协作。然而&#xff0c;在市场上有许多不同的任务管理工具可供选择&#xff0c;因此选择适合团队的最佳工具可能会成…

设计师必备的插画设计素材网站

趋势很快就会下降&#xff0c;而新浪潮很快就会席卷而来。 品牌和设计师都意识到&#xff0c;他们需要放松僵化的自信&#xff0c;成为开放的团队合作伙伴。如果你对创意工作或趋势保持好奇&#xff0c;这些创意网站会让你摆脱混合的网页搜索推荐&#xff0c;帮助你获得最专业…

ICLR 2024 再现抄袭风波!原作者发帖实锤:过半方法都抄了

添加图片注释&#xff0c;不超过 140 字&#xff08;可选&#xff09; 夕小瑶科技说 原创 作者 | 智商掉了一地、ZenMoore 就在上个月末&#xff0c;ICLR 2024 的提交告一段落&#xff0c;在 OpenReview 上已经能够看到目前提交的文章了。虽然评阅结果尚未被发布&#xff0c;…

生成式AI - 大模型(LLM)提示工程(Prompt)技巧

提示工程可以描述为一种艺术形式&#xff0c;为大型语言模型&#xff08;LLMs&#xff09;创建输入请求&#xff0c;以实现预期的输出。以下是创造单个或一系列提示的不同技巧。 由少到多的提示 推理过程是基于证据和推理得出结论。反过来&#xff0c;可以通过为LLM提供一些关于…

【数据结构】模拟实现栈和队列

文章目录 栈&#xff08;Stack&#xff09;栈的概念栈的常用方法模拟实现栈 队列&#xff08;Queue&#xff09;队列的概念队列的常用方法队列的模拟实现循环队列模拟实现 栈&#xff08;Stack&#xff09; 栈的概念 栈是一种特殊的线性表&#xff0c;只允许在固定的一端进行…

CSS背景background八种属性

想必大家对背景不陌生&#xff0c;让我为大家介绍一下吧&#xff01; 属性名简述background-color背景颜色background-image背景图片background-position背景定位background-size背景大小background-repeat背景是否平铺background-attachment背景是否随滚动条固定background-c…

计算机网络【CN】介质访问控制

信道划分介质访问控制 FDMTDMWDMCDM【掌握eg即可】 随机介质访问控制 CSMA 1-坚持CSMA 非坚持CSMA p-坚持CSMA 空闲时 立即发送数据 立即发送数据 以概率P发送数据&#xff0c;以概率1-p推迟到下一个时隙 忙碌时 继续坚持侦听 放弃侦听&#xff0c;等待一个随机的时…

SAP数据元素描述增强修改

数据元素描述增强修改 一、需求 需要将业务伙伴伙伴中的手机字段的描述改为’税局备案电话’。 三、增强实现 使用事务码CMOD&#xff0c;点击转到-》文本增强-》关键字-》更改。 输入数据元素的的字段号码&#xff0c;更改激活即可

从瀑布模式到水母模式:ChatGPT如何赋能软件研发全流程【文末送书五本】

从瀑布模式到水母模式&#xff1a;ChatGPT如何赋能软件研发全流程 前言内容简介购买链接作者简介专家推荐读者对象参与方式往期赠书回 &#x1f3d8;️&#x1f3d8;️个人简介&#xff1a;以山河作礼。 &#x1f396;️&#x1f396;️:Python领域新星创作者&#xff0c;CSDN实…

Unity的碰撞检测(五)

温馨提示&#xff1a;本文基于前一篇“Unity的碰撞检测(四)​​​​​​​”继续探讨两个游戏对象具备刚体的BodyType均为Dynamic&#xff0c;但是Collision Detection属性不同的碰撞检测&#xff0c;阅读本文则默认已阅读前文。 &#xff08;一&#xff09;测试说明 在基于两…

《动手学深度学习 Pytorch版》 10.7 Transformer

自注意力同时具有并行计算和最短的最大路径长度这两个优势。Transformer 模型完全基于注意力机制&#xff0c;没有任何卷积层或循环神经网络层。尽管 Transformer 最初是应用于在文本数据上的序列到序列学习&#xff0c;但现在已经推广到各种现代的深度学习中&#xff0c;例如语…

QA新人入职任务

一、背景 分享记录一下入职新公司后&#xff0c;新人第一周接到的新手任务&#xff0c;回顾总结&#xff0c;方便自己成长和思考~ 二、新人任务说明 题目1&#xff1a;接口相关 题目2&#xff1a;UI相关 UI原型图 三、任务要求 1、根据题目2原型图&#xff0c;进行UI测试…

【继承顺序和方式,子类构造方法,protected 关键字,final 关键字】

文章目录 子类构造方法super和this继承关系上的执行顺序protected 关键字继承方式final 关键字总结 子类构造方法 子类继承父类的成员变量&#xff0c;那父类的成员变量怎么初始化呢&#xff1f; 要先初始化父类成员&#xff0c;子类的构造方法才能完成 class Animal{public…

解决:idea中代码文件背景变成特殊颜色(浅褐色),且代码智能提示完全消失,即使在新项目中创建同类型文件也会出现同样情况

解决&#xff1a;idea开发中代码文件背景变成浅褐色&#xff0c;且代码智能提示完全消失&#xff0c;不同项目新建同类型文件也会出现同样情况 一问题描述&#xff1a;1.idea开发中&#xff0c;使用idea的快捷提示组合键进行提示&#xff0c;但是手快点击确认了什么提示选项&am…

DSP开发例程(3): sys_print_to_uart

目录 DSP开发例程: sys_print_to_uart创建工程源码编辑os.capp.cfgmain.c 调试原理分析 DSP开发例程: sys_print_to_uart 在DSP 应用的执行过程中, 我们经常需要调用 System_printf() 来显示当前的执行状态. 不只是 System_printf() 函数, SYS/BIOS 打印信息的函数还包括: Sys…

橙河网络:国外问卷调查赚钱是真的吗?

大家好&#xff0c;我是橙河网络&#xff0c;今天聊一聊国外问卷调查赚钱是真的吗&#xff1f; 有不少人在第一次了解这个项目的时候&#xff0c;看到“海外”“国外”这些字眼的时候&#xff0c;心里都会犯嘀咕&#xff1a;这海外问卷调查项目能做吗&#xff1f;国外问卷调查…

使用 Pyro 和 PyTorch 的贝叶斯神经网络

一、说明 构建图像分类器已成为新的“hello world”。还记得当你第一次接触 Python 时&#xff0c;你的打印“hello world”感觉很神奇吗&#xff1f;几个月前&#xff0c;当我按照PyTorch 官方教程并为自己构建了一个运行良好的简单分类器时&#xff0c;我也有同样的感觉。 我…