Java整数缓存-为什么Integer.valueOf(127)== Integer.valueOf(127)为True
在一次采访中,我的一个朋友被问到如果我们有两个Integer对象, Integer a = 127; Integer b = 127;
Integer a = 127; Integer b = 127;
为什么当a == b
都持有两个单独的对象时,其值为true
? 在本文中,我将尝试回答这个问题,并尝试解释答案。
简短答案
这个问题的简短答案是,将int
常量直接分配给Integer
引用是自动装箱概念的一个示例,在该示例中,由编译器处理到对象转换代码的常量值,因此在编译阶段,编译器将Integer a = 127;
转换为Integer a = 127;
Integer a = Integer.valueOf(127);
。
Integer
类为内部整数维护一个内部IntegerCache,这些整数默认范围为-128 to 127
并且Integer.valueOf()
方法从该缓存中返回上述范围的对象。 因此a == b
返回true,因为a
和b
都指向同一个对象。
长答案
为了理解简短的答案,让我们首先了解Java类型,Java中的所有类型都分为两类
- 基本类型: Java中有8种基本类型(字节,短型,整型,长型,浮点型,双精度型,字符型和布尔型),它们直接以二进制位的形式保存其值。
例如int a = 5; int b = 5;
int a = 5; int b = 5;
这里a
和b
直接持有的5二进制值,如果我们试图比较a
和b
使用a == b
我们实际上是在比较5 == 5
返回true。 - 引用类型:除基本类型外,所有其他类型都位于引用类型的类别下,例如类,接口,枚举,数组等,引用类型保存对象的地址,而不是对象iteslf。
例如,Integer a = new Integer(5); Integer b = new Integer(5)
Integer a = new Integer(5); Integer b = new Integer(5)
,此处a和b不保存二进制值5
而是a
和b
保存两个单独对象的内存地址,其中两个对象都包含值5
。 因此,如果尝试使用a == b,
比较a
和b
a == b,
则实际上是在比较这两个单独的内存地址,因此我们得到false
,要对a
和b
执行实际相等,需要执行a.euqals(b)
。 引用类型又分为4类: 强引用,软引用,弱引用和幻像引用 。
而且我们知道Java为所有原始类型提供包装器类,并支持自动装箱和自动拆箱。
// Example of auto-boxing, here c is a reference type
Integer c = 128; // Compiler converts this line to Integer c = Integer.valueOf(128); // Example of auto-unboxing, here e is a primitive type
int e = c; // Compiler converts this line to int e = c.intValue();
现在,如果我们创建两个整数对象a
和b,
并尝试使用相等运算符==
进行比较,则将得到false
因为两个引用都持有不同的对象
Integer a = 128; // Compiler converts this line to Integer a = Integer.valueOf(128);
Integer b = 128; // Compiler converts this line to Integer b = Integer.valueOf(128);System.out.println(a == b); // Output -- false
但是,如果我们为a
和b
都分配值127
并尝试使用等于运算符==
进行比较,那么为什么会true
?
Integer a = 127; // Compiler converts this line to Integer a = Integer.valueOf(127);
Integer b = 127; // Compiler converts this line to Integer b = Integer.valueOf(127);System.out.println(a == b); // Output -- true
正如我们在代码中看到的那样,我们为a
和b
分配了不同的对象,但是只有当a
和b
都指向同一个对象时, a == b
才能返回true。
那么比较如何返回true? 这里到底发生了什么? 是a
和b
指向相同的对象?
到目前为止,我们知道代码Integer a = 127;
是自动装箱的示例,编译器自动将此行转换为Integer a = Integer.valueOf(127);
。
因此,正是Integer.valueOf()
方法返回这些整数对象,这意味着该方法必须在幕后进行某些操作。
并且,如果我们看一下Integer.valueOf()
方法的源代码,我们可以清楚地看到,如果传递的int文字i
大于IntegerCache.low
且小于IntegerCache.high
则该方法从IntegerCache
返回Integer对象。 IntegerCache.low
和IntegerCache.high
默认值分别是-128
和127
。
换句话说而不是创建和retruning新的整数对象, Integer.valueOf()
方法返回整数从内部对象IntegerCache
如果传递的INT字面大于
-128
且小于127
。
/*** 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);}
Java缓存落入-128到127范围内的整数对象,因为该整数范围在日常编程中被大量使用,从而间接节省了一些内存。
如您在下图中所看到的, Integer
类维护一个内部静态IntegerCache
类,该类充当缓存并保存从-128到127的整数对象,这就是为什么当我们尝试获取127
整数对象时总是得到相同的对象。
当类由于static block
而被加载到内存时,首次使用时将初始化缓存。 高速缓存的最大范围可以由-XX:AutoBoxCacheMax
JVM选项控制。
此缓存行为仅适用于Integer
对象,类似于Integer.IntegerCache
我们还有ByteCache
, ShortCache
, LongCache
, Byte
CharacterCache
, Short
,
Long
, Character
。
Byte,Short和Long具有固定的缓存范围,介于–127到127(含)之间,而Character的范围是0到127(含)之间。 只能通过参数对Integer修改范围,而不能对其他参数进行修改。
您可以在此Github存储库中找到本文的完整源代码,请随时提供宝贵的反馈。
翻译自: https://www.javacodegeeks.com/2018/11/integer-cache-integer-valueof127-true.html
Java整数缓存-为什么Integer.valueOf(127)== Integer.valueOf(127)为True相关推荐
- integer比较_Java整数缓存Integer.valueOf(127)==Integer.valueOf(127)为True
在一次采访中,我的一个朋友被问到,如果我们有两个整数对象,Integer a = 127; Integer b = 127;为什么要a == b的值为true ?在本文中,我将尝试回答这个问题,并解释 ...
- Java 8 中 Byte、Short、Integer、Long内部缓存类的对比与源码分析
这是<水煮 JDK 源码>系列 的第7篇文章,计划撰写100篇关于JDK源码相关的文章 对于基本数据类型的包装类 Byte.Short.Integer.Long ,其内部实现都有一个缓存类 ...
- Integer.valueof()和Integer.parseInt()的区别
Integer. valueOf()可以将基本类型int转换为包装类型Integer,或者将String转换成Integer,String如果为Null或""都会报错. Integ ...
- int、Integer、new Integer和Integer.valueOf()的 ==、equals比较
Java 基本数据类型的包装类型的大部分都用到了缓存机制来提升性能. Byte,Short,Integer,Long 这 4 种包装类默认创建了数值 [-128,127] 的相应类型的缓存数据,Cha ...
- Integer的值范围-128~127
看到一道面试题,这个面试题是这样的. public class Foo {public static void main(String[] args) {Integer a = 120,b = 160 ...
- 【Java】中int 和 Integer 与 new Integer() 的区别,int 可以使用 == 来对比两个变量是否相等,而 Integer 一定要使用 equals 来比较两个变量值是否相等
目录 一.int 和 Integer 的区别 二. Integer.new Integer() 和 int 的比较 三.总结 四.更多详看: 一.int 和 Integer 的区别 两者的区别主要体现 ...
- Java中Int、Integer、new Integer()之间的区别
Java中有八种基本数据类型,Int是其中之一.而Integer是Int的封装,即Integer其实是一个对象.可以通过new来创建一个Integer对象,也可以直接将Int值赋给Integer变量. ...
- 016 Java中 int、Integer和 new Integer() 使用==比较
Java中 int.Integer和 new Integer() 使用==比较 int则是java的一种基本数据类型,其定义的是基本数据类型变量 :Integer是int的包装类,其定义的是引用类型变 ...
- java中的int、Integer 和 new Integer()的区分和比较
java中的int.Integer 和 new Integer()的区分和比较 一.问题提出: 1.1.问题一: int a = 2; Integer b = 2; Integer c = new I ...
最新文章
- A 'return' expression required in a function with a block body ('{...}')
- 指尖上的电商---(4).net开发solr
- MIT、CMU 美国计算机专业最牛20名学校大点评
- 程序员从入门到升级,或许可以看一看这几个公众号
- 苹果企业账号使用注意事项
- vue项目电商后台管理系统(一)
- 计算机解八元一次方程,如何用matlab求解8元一次,含参数的方程组(共八个一次方程)...
- TensorFlow 2.10 Unable to register cuBLAS factory Attempting to register factory for plugin cuBLAS方案
- 安卓手机上最好的3个小说阅读器
- 台式计算机可以发射无线网络,台式电脑wifi发射教程
- [转]XPO 条件相关类
- (三)DQL数据库指令
- 接入高防后出现502怎么办?
- Bug: Return value of putIfAbsent is ignored, but list is reused
- 树莓派安装smbus_如何配置树莓派并安装有用的库
- Java单位重量转换_Java实现蓝桥杯单位转换
- 软件测试之测试计划与工具(三)
- 大学计算机比赛保送,他是信息奥赛金牌得主,保送清华姚班!初中打游戏经常被老师抓...
- OpenGL与DirectX 比较
- zero:seo技术领域的搜索引擎优化指南
热门文章
- 2017西安交大ACM小学期 敏感词汇[AC自动机]
- 解决idea启动项目报错:Unable to open debugger port(127.0.0.1:60157):java.net.SocketExceptionsocket closed
- 一文告诉你 Java RMI 和 RPC 的区别
- java并发编程(二十一)----(JUC集合)CopyOnWriteArraySet和ConcurrentSkipListSet介绍
- hashCode到底有什么用?
- 算法一之简单选择排序
- Hibernate之映射
- Js对象如何添加方法、查看Api
- 集合打印出来的信息不是输入的信息
- Spark之Master主备切换机制原理