在一次采访中,我的一个朋友被问到如果我们有两个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,因为ab都指向同一个对象。

长答案

为了理解简短的答案,让我们首先了解Java类型,Java中的所有类型都分为两类

  1. 基本类型: Java中有8种基本类型(字节,短型,整型,长型,浮点型,双精度型,字符型和布尔型),它们直接以二进制位的形式保存其值。
    例如int a = 5; int b = 5; int a = 5; int b = 5; 这里ab直接持有的5二进制值,如果我们试图比较ab使用a == b我们实际上是在比较5 == 5返回true。
  2. 引用类型:除基本类型外,所有其他类型都位于引用类型的类别下,例如类,接口,枚举,数组等,引用类型保存对象的地址,而不是对象iteslf。
    例如, Integer a = new Integer(5); Integer b = new Integer(5) Integer a = new Integer(5); Integer b = new Integer(5) ,此处a和b不保存二进制值5而是ab保存两个单独对象的内存地址,其中两个对象都包含值5 。 因此,如果尝试使用a == b,比较ab a == b,则实际上是在比较这两个单独的内存地址,因此我们得到false ,要对ab执行实际相等,需要执行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();

现在,如果我们创建两个整数对象ab,并尝试使用相等运算符==进行比较,则将得到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

但是,如果我们为ab都分配值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

正如我们在代码中看到的那样,我们为ab分配了不同的对象,但是只有当ab都指向同一个对象时, a == b才能返回true。

那么比较如何返回true? 这里到底发生了什么? 是ab指向相同的对象?

到目前为止,我们知道代码Integer a = 127; 是自动装箱的示例,编译器自动将此行转换为Integer a = Integer.valueOf(127);

因此,正是Integer.valueOf()方法返回这些整数对象,这意味着该方法必须在幕后进行某些操作。

并且,如果我们看一下Integer.valueOf()方法的源代码,我们可以清楚地看到,如果传递的int文字i大于IntegerCache.low且小于IntegerCache.high则该方法从IntegerCache返回Integer对象。 IntegerCache.lowIntegerCache.high默认值分别是-128127

换句话说而不是创建和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我们还有ByteCacheShortCacheLongCacheByte CharacterCacheShort
LongCharacter

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相关推荐

  1. integer比较_Java整数缓存Integer.valueOf(127)==Integer.valueOf(127)为True

    在一次采访中,我的一个朋友被问到,如果我们有两个整数对象,Integer a = 127; Integer b = 127;为什么要a == b的值为true ?在本文中,我将尝试回答这个问题,并解释 ...

  2. Java 8 中 Byte、Short、Integer、Long内部缓存类的对比与源码分析

    这是<水煮 JDK 源码>系列 的第7篇文章,计划撰写100篇关于JDK源码相关的文章 对于基本数据类型的包装类 Byte.Short.Integer.Long ,其内部实现都有一个缓存类 ...

  3. Integer.valueof()和Integer.parseInt()的区别

    Integer. valueOf()可以将基本类型int转换为包装类型Integer,或者将String转换成Integer,String如果为Null或""都会报错. Integ ...

  4. int、Integer、new Integer和Integer.valueOf()的 ==、equals比较

    Java 基本数据类型的包装类型的大部分都用到了缓存机制来提升性能. Byte,Short,Integer,Long 这 4 种包装类默认创建了数值 [-128,127] 的相应类型的缓存数据,Cha ...

  5. Integer的值范围-128~127

    看到一道面试题,这个面试题是这样的. public class Foo {public static void main(String[] args) {Integer a = 120,b = 160 ...

  6. 【Java】中int 和 Integer 与 new Integer() 的区别,int 可以使用 == 来对比两个变量是否相等,而 Integer 一定要使用 equals 来比较两个变量值是否相等

    目录 一.int 和 Integer 的区别 二. Integer.new Integer() 和 int 的比较 三.总结 四.更多详看: 一.int 和 Integer 的区别 两者的区别主要体现 ...

  7. Java中Int、Integer、new Integer()之间的区别

    Java中有八种基本数据类型,Int是其中之一.而Integer是Int的封装,即Integer其实是一个对象.可以通过new来创建一个Integer对象,也可以直接将Int值赋给Integer变量. ...

  8. 016 Java中 int、Integer和 new Integer() 使用==比较

    Java中 int.Integer和 new Integer() 使用==比较 int则是java的一种基本数据类型,其定义的是基本数据类型变量 :Integer是int的包装类,其定义的是引用类型变 ...

  9. java中的int、Integer 和 new Integer()的区分和比较

    java中的int.Integer 和 new Integer()的区分和比较 一.问题提出: 1.1.问题一: int a = 2; Integer b = 2; Integer c = new I ...

最新文章

  1. A 'return' expression required in a function with a block body ('{...}')
  2. 指尖上的电商---(4).net开发solr
  3. MIT、CMU 美国计算机专业最牛20名学校大点评
  4. 程序员从入门到升级,或许可以看一看这几个公众号
  5. 苹果企业账号使用注意事项
  6. vue项目电商后台管理系统(一)
  7. 计算机解八元一次方程,如何用matlab求解8元一次,含参数的方程组(共八个一次方程)...
  8. TensorFlow 2.10 Unable to register cuBLAS factory Attempting to register factory for plugin cuBLAS方案
  9. 安卓手机上最好的3个小说阅读器
  10. 台式计算机可以发射无线网络,台式电脑wifi发射教程
  11. [转]XPO 条件相关类
  12. (三)DQL数据库指令
  13. 接入高防后出现502怎么办?
  14. Bug: Return value of putIfAbsent is ignored, but list is reused
  15. 树莓派安装smbus_如何配置树莓派并安装有用的库
  16. Java单位重量转换_Java实现蓝桥杯单位转换
  17. 软件测试之测试计划与工具(三)
  18. 大学计算机比赛保送,他是信息奥赛金牌得主,保送清华姚班!初中打游戏经常被老师抓...
  19. OpenGL与DirectX 比较
  20. zero:seo技术领域的搜索引擎优化指南

热门文章

  1. 2017西安交大ACM小学期 敏感词汇[AC自动机]
  2. 解决idea启动项目报错:Unable to open debugger port(127.0.0.1:60157):java.net.SocketExceptionsocket closed
  3. 一文告诉你 Java RMI 和 RPC 的区别
  4. java并发编程(二十一)----(JUC集合)CopyOnWriteArraySet和ConcurrentSkipListSet介绍
  5. hashCode到底有什么用?
  6. 算法一之简单选择排序
  7. Hibernate之映射
  8. Js对象如何添加方法、查看Api
  9. 集合打印出来的信息不是输入的信息
  10. Spark之Master主备切换机制原理