【笔记】经典Integer对象赋值128问题

Integer经典面试问题:两个Integer对象都赋值为128,这两个对象比较是否相同?为什么?

回答这个问题,首先我们要知道,在Java中,当你写Integer a = 1; 实际上是调用了Java的自动装箱功能。这会将整数 1 自动装箱为Integer对象,然后将这个对象赋值给变量a。

自动装箱功能是由编译器自动插入的,实际上它相当于执行了如下的代码:

Integer a = Integer.valueOf(1);

这里的valueOf方法是Integer类的一个静态方法,它的作用就是将传入的参数(通常是基本数据类型)自动转换为对应的包装类对象。对于Integer类来说,就是将整数值转换为Integer对象。

知道这一点之后,我们看看Integer.valueOf方法的源码:

/*** 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);
}

注解上说:如果不需要新的Integer实例,则通常应该优先使用此方法,而不是构造函数Integer(int),因为通过缓存频繁请求的值,该方法可能会产生更好的空间和时间性能。此方法将始终缓存-128到127(包括-128到127)范围内的值,并可能缓存此范围之外的其他值。

接下来看看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 propertyint 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_VALUEh = 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=选项来控制。在虚拟机初始化过程中,可以设置java.lang.Integer.IntegerCache.high属性,并保存在sun.misc.VM类的私有系统属性中。

IntegerCache缓存范围的最小值固定为-128,最大值默认为127.但是最大值是可以被重新定义的,那么可定义的范围是多少呢?

i = Math.max(i, 127);
// Maximum array size is Integer.MAX_VALUE
h = Math.min(i, Integer.MAX_VALUE - (-low) -1);

上面的两行已经定义了IntegerCache缓存最大值的范围:

  1. 定义最大值范围大于等于127;

  2. 定义最大值范围小于等于Integer.MAX_VALUE - (-low) -1;

Integer.MAX_VALUE的定义:(2的23次方 - 1)

@Native public static final int   MAX_VALUE = 0x7fffffff;

IntegerCache缓存的范围定义好后,为区间范围赋值。

for(int k = 0; k < cache.length; k++)cache[k] = new Integer(j++);

最后通过断言检查 IntegerCache.high 是否大于等于 127。

// range [-128, 127] must be interned (JLS7 5.1.7)
assert IntegerCache.high >= 127;

IntegerCache.high 是 Java 中 Integer 缓存的一部分,这个缓存用于存储 -128 到 127 之间的整数,以提高这个范围内的整数在多次使用时的性能。

assert 是一个用于调试的语句,当 IntegerCache.high < 127 时,该语句将抛出 AssertionError

JLS7 5.1.7 是 Java Language Specification 的一个部分,这部分规定了对于字符串字面值,编译器必须将它们在编译期放入字符串池中,以避免内存浪费。

这段代码的目的是确保 IntegerCache 的范围在 [-128, 127] 内,因为这是 String 缓存这个优化策略可以应用的范围。如果 IntegerCache 的范围超出了这个范围,那么可能会导致无法进行这种优化,从而可能降低性能。

需要注意的是,assert 语句在默认情况下是关闭的,如果你想要开启它,需要在启动 JVM 时添加 -ea(或 -enableassertions)参数。

因此,当写 Integer i1 = 128;Integer i2 = 128; ,实际上在内存中创建了两个不同的对象,即使它们包含相同的值。

可以通过调用 equals() 方法来比较这两个对象的内容是否相同,而不是使用 == 运算符。这是因为 ==在比较对象时实际上是检查它们是否指向内存中的同一个对象,而不是比较它们的内容。而 equals() 方法则是比较对象的内容。

如果使用 equals() 方法来比较这两个对象,它们会被视为相等,因为它们包含相同的内容。但是,如果你使用 ==运算符来比较,它们会被视为不相等,因为它们是不同的对象。

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

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

相关文章

Redis7安装

1. 使用什么系统安装redis 由于企业里面做Redis开发&#xff0c;99%都是Linux版的运用和安装&#xff0c;几乎不会涉及到Windows版&#xff0c;上一步的讲解只是为了知识的完整性&#xff0c;Windows版不作为重点&#xff0c;同学可以下去自己玩&#xff0c;企业实战就认一个版…

几个nlp的小任务(抽取式问答)

几个nlp的小任务(抽取式问答) 安装库抽取式问答介绍、SQuAD数据集初始化参数加载、导入数据集查看数据集示例加载tokenizer对长文本处理的演示对答案的位置进行验证整合刚才的步骤对数据集中的数据进行预处理加载微调模型设置args 参数使用数据清洗设置训练函数,开始训练安装…

从零学算法 (剑指 Offer 13)

地上有一个m行n列的方格&#xff0c;从坐标 [0,0] 到坐标 [m-1,n-1] 。一个机器人从坐标 [0, 0] 的格子开始移动&#xff0c;它每次可以向左、右、上、下移动一格&#xff08;不能移动到方格外&#xff09;&#xff0c;也不能进入行坐标和列坐标的数位之和大于k的格子。例如&am…

STM32开发 | 移远4G-Cat.1模组EC200N-CN开发

一、硬件说明 1、引脚分配图 文章来源地址https://www.yii666.com/blog/326636.html文章来源地址:https://www.yii666.com/blog/326636.html 2、常用引脚说明 模块输入电源 引脚名描述VBAT_BB模块基带电源&#xff08;Vnom 3.8 V&#xff09;VBAT_RF模块射频电源&#xff0…

Linux操作系统--常用指令(帮助命令)

(1).概述 在日常生活中,我们遇到不认识的字怎么办?小学的时候,我们知道我们可以查字典来认识这一个字,那么如果是Linux操作系统中遇到不认识的指令,该怎么办呢?同样,linux提供了帮助命令以便于我们更好的认识这一个指令。下面我们一起来看一下Linux操作系统提供给我们的…

软件测试技术分享丨使用Postman搞定各种接口token实战

现在许多项目都使用jwt来实现用户登录和数据权限&#xff0c;校验过用户的用户名和密码后&#xff0c;会向用户响应一段经过加密的token&#xff0c;在这段token中可能储存了数据权限等&#xff0c;在后期的访问中&#xff0c;需要携带这段token&#xff0c;后台解析这段token才…

设计模式之工厂方法模式

目录 工厂方法模式 简介 优缺点 结构 使用场景 实现 1.抽象产品 2.具体产品 3.抽象工厂 4.具体工厂 5.调用 总结 抽象工厂模式 简介 结构 实现 区别 工厂方法模式 简介 提供一个用于创建对象的接口(工厂接口)&#xff0c;让其实现类(工厂实现类)决定实例化哪…

Redis内存策略

文章目录 Redis内存策略过期策略DB结构惰性删除周期删除 淘汰策略 Redis内存策略 Redis是基于内存存储&#xff0c;所以其性能很强。但单节点的Redis内存不宜过大&#xff0c;否则会影响持久化或主从同步性能。 可以手动修改配置文件来设置Redis的最大内存 # 格式&#xff1…

【Unity3D赛车游戏】【五】Unity中汽车加速效果是如何优化的?

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 秩沅 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a;Uni…

【滑动窗口】leetcode3:无重复字符的最长子串

一.题目描述 无重复字符的最长子串 二.思路分析 题目要求我们找符合要求的最长子串&#xff0c;要求是不能包含重复字符 确定一个子串只需确定它的左右区间即可&#xff0c;于是我们可以两层循环暴力枚举所有的子串&#xff0c;找到符合要求的&#xff0c;并通过比较得到最长…

软件工程(十五) 行为型设计模式(一)

1、责任链模式 简要说明 通过多个对象处理的请求,减少请求的发送者与接收者之间的耦合。将接受对象链接起来,在链中传递请求,直到有一个对象处理这个请求。 速记关键字 传递职责 类图如下 由类图可以比较容易的看出来,其实就是自己关联自己,形成了一个链,并且自己有…

链表的实现

本程序List链表用两种方式实现&#xff0c;一种是双向链表&#xff0c;一种是双向循环链表。循环双向链表和双向链表&#xff0c;它们的编码差别很小&#xff1b;但是循环链表在插入效率上胜出很多&#xff0c;同时查询时候更灵活。综合考虑&#xff0c;循环链表是首选。 另外…

等保测评--安全通信网络--测评方法

安全子类--安全架构 a)应保证网络设备的业务处理能力满足业务高峰期需要; 一、测评对象 路由器、交换机、无线接入设备和防火墙等提供网络通信功能的设备或相关组件 二、测评实施 1) 应核查业务高峰时期一段时间内主要网络设备(一般包括核心交换机、汇聚交换机、边界路…

JavaScript伪协议是什么?

JavaScript伪协议是什么&#xff1f; 伪协议不同于因特网上所真实存在的协议&#xff0c;如http://&#xff0c;https://&#xff0c;ftp://&#xff0c; 而是为关联应用程序而使用的.如:tencent://(关联QQ)&#xff0c;data:(用base64编码来在浏览器端输出二进制文件)&#xf…

vue 04-reactive与ref的选择

reactive与re两者区别&#xff1f; reactive可以转换对象成为响应式数据对象,但是不支持简单数据类型 ref可以转换简单数据类型为响应式数据对象,也支持复杂数据类型,但是操作的时候需要.value 推荐使用的话: 如果能确定数据是对象且字段名称也确定,可以使用reactive转成响应式…

❤ leetCode简易2--回文数判断

❤ leetCode简易2–回文数判断 题目要求判断回文数 给你一个整数 x &#xff0c;如果 x 是一个回文整数&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 回文数是指正序&#xff08;从左向右&#xff09;和倒序&#xff08;从右向左&#xff09;读都是一样的…

解锁Selenium的力量:不仅仅是Web测试

Selenium简介 Selenium&#xff0c;作为Web应用测试的领军者&#xff0c;已经成为了无数开发者和测试人员的首选工具。它不仅仅是一个自动化测试工具&#xff0c;更是一个强大的Web应用交互框架。 Selenium的起源与发展 Selenium的历史可以追溯到2004年&#xff0c;由Jason Hu…

CGLIB代理,jsp,EL表达式,JSTL标准标签库

1、CGLIB代理 有一个类没有实现接口&#xff0c;想要对这个类实现增强&#xff0c;就需要使用CGLIB代理 导入CGLIB的包 <dependency><groupId>cglib</groupId><artifactId>cglib</artifactId><version>3.3.0</version> </depende…

VictoriaLogs:一款超低占用的 ElasticSearch 替代方案

image.png 背景 前段时间我们想实现 Pulsar 消息的追踪流程&#xff0c;追踪实现的效果图如下&#xff1a; 实现其实比较简单&#xff0c;其中最重要的就是如何存储消息。 消息的读取我们是通过 Pulsar 自带的 BrokerInterceptor 实现的&#xff0c;对这个感兴趣的朋友后面会单…

【Electron】使用electron-builder打包时下载electron失败或慢的解决方案

问题描述 electron-builder打包时报错信息如下&#xff1a; Building app with electron-builder:• electron-builder version22.14.5 os10.0.19042• description is missed in the package.json appPackageFileE:\h-world\hscmweb-diagrams\dist_electron\bundled\packa…