我们先看一段代码:

 public static void main(String[] args) {Integer i1 = 20;Integer i2 = 20;System.out.println(i1 == i2);System.out.println(i1.equals(i2));}

接着往下看之前,大家可以先自己想一想输出结果是什么。

 输出结果:ture true

如果代码换成这样呢:

 public static void main(String[] args) {Integer i1 = 200;Integer i2 = 200;System.out.println(i1 == i2);System.out.println(i1.equals(i2));}

两次输出结果会有什么不一样呢?

 这次输出的是 false true

为什么会是这样呢?
首先,我们看一下双等号“ == ”和equals()方法的不同之处。
双等号“ == ”,对于基本数据类型,比较的是它们的值。
对于非基本类型,比较的是它们在内存中的存放地址,或者说是比较两个引用是否引用内存中的同一个对象。

equals()是在Object基类中定义的方法。
这个方法的初始行为是比较对象的内存地址,但在一些类库中,这个方法被覆盖掉了,如String,Integer,Date等。在这些类当中equals有其自身的实现,而不再是比较类在堆内存中的存放地址了。
对于复合数据类型之间进行equals比较,在没有覆写equals方法的情况下,它们之间的比较还是基于他们在内存中的存放位置的地址值的,因为Object的equals方法也是用双等号“ == ”进行比较的,所以比较后的结果跟双等号“ == ”的结果相同。

Integer.class中源代码:

     public boolean equals(Object obj) {if (obj instanceof Integer) {return value == ((Integer)obj).intValue();}return false;}

可以看到,Integer中比较的是值。

因此,两次i1.equals(i2)返回的都是true。

为什么 i1 == i2两次输出结果不一致呢?我们分析一下代码:

Integer i1 = 20,Integer是包装类型,20是整形常量,所以这里涉及到自动装箱过程,i1是Integer的引用,指向20这个整形常量所占用的内存。

Integer i1 = 20 或者Integer i1 = 200的时候,会调用 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);}

这段代码的作用是把int类型转换成Integer,也就是装箱,它返回一个 Integer对象。
这里又涉及到IntegerCache,对于这段静态代码(这里JDK版本是JDK1.8):

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

这段代码的作用是,在Integer类装载入内存时,把[-128, 127]范围内的整型数据装包成Integer类,并将其对应的引用放入到cache数组中。

从上面的源码可以看出,valueOf()在返回之前,会进行判断,判断当前 i的值是否在 -128到127之间。
如果存在,则直接返回引用,不再重新开辟内存空间。
如果不存在,就创建一个新的对象。
利用缓存,这样做既能提高程序执行效率,还能节约内存。

Integer i1 = 20; Integer i2 = 20; 因为 IntegerCache中已经存在此对象,直接返回引用,引用相等并且都指向缓存中的数据,所以这时候i1 == i2返回true。

Integer i1 = 200; Integer i2 = 200;因为i1,i2的值大于127,不在[-128, 127]范围内,所以虚拟机会在堆中重新new一个 Integer对象来存放200,创建两个对象就会产生两个这样的空间。两个空间的地址不同,返回到栈中的引用的值也就不同,所以这时候i1 == i2返回false。

以上是我的一些踩坑记录,有什么不足和错误之处,欢迎指正。

Java中Integer.valueOf()解读相关推荐

  1. Java 中 Integer 源码学习之缓存池了解

    Java 中 Integer 源码学习之缓存池了解 面试题 new Integer(123) 与 Integer.valueOf(123) 的区别? new Integer(123) 每次都会新建一个 ...

  2. JAVA中Integer的==和equals

    JAVA中Integer的==和equals注意 "equals"比较 equals(Object obj)方法,在equals(Object obj)方法中,会先判断参数中的对象 ...

  3. java中integer取值范围,Java中的Integer取值范围(-2^32 ~ 2^31 - 1)分析

    在Java中Integer的最小值(MIN_VALUE).最大值(MAX_VALUE)定义如下: /** * A constant holding the minimum value an {@cod ...

  4. java 中 Integer 比较 问题

    对于 java 中 Integer  类型 比较 ,经常在面试中被提到 ,有时 还真的 让人 头疼.下面我来分析下.integer   比较问题. 解决 Integer 值比较问题.我想从以下几点说起 ...

  5. java中Integer的最大最小值

    java中Integer是有最大值和最小值的 最大值为Integer.MAX_VALUE = 2147483647 最小值为Integer.MIN_VALUE = -2147483648 注意:两个值 ...

  6. java中integer的范围_java中integer取值范围是什么

    java中integer取值范围是什么 发布时间:2020-08-27 10:01:14 来源:亿速云 阅读:69 作者:小新 这篇文章给大家分享的是有关java中integer取值范围是什么的内容. ...

  7. Java中Integer超出范围问题

    Java中Integer超出范围问题 Java中Integer范围 在Java中Integer范围是2-31到231-1,但是如果超过范围怎么处理? 使用左移运算验证 左移运算<<,将二进 ...

  8. java中Integer.parseInt和Integer.valueOf 的区别

    他们返回类型的不同是最大的原因. static int parseInt(String s) 将字符串参数作为有符号的十进制整数进行分析.static Integer valueOf(int i) 返 ...

  9. Java中Integer的valueOf()方法

    valueOf()包含包含3个相互重载的具体方法. 一.valueOf(String s, int radix) 该方法将字符串s中隐含的数字按照radix指定的进制解析为10进制整数,如果字符串s中 ...

最新文章

  1. OpenCV(十四)图像阈值
  2. DataGridView取得或者修改当前单元格的内容
  3. java 变长参数 知乎_变长参数探究
  4. wget: unable to resolve host address “mirrors.163.com” 的解决办法
  5. 用clipboard.js实现纯JS复制文本到剪切板
  6. Win11怎么从Dev渠道换Beta渠道?Win11从Dev渠道换Beta渠道的方法
  7. python 面向对象的封装_Python面向对象封装操作案例详解
  8. 什么是deployment 声明式升级应用
  9. 包级别的 TCP/UDP 负载均衡和NAT(Network Address Translate)
  10. 大数据Hadoop生态圈
  11. 服务器添加hdr文件3dMax,别再乱用HDR了!关于它的10件事你该知道
  12. MATLAB GUI 设全局变量的位置
  13. 微信小程序 获取用户昵称、头像、手机号
  14. ISO15765协议
  15. [个人记录]春招C/C++后台/运维面试被问到的那些知识点(第一周)
  16. 迪士尼机器人芭蕾舞_迪士尼乐园里的机器人又有新消息,这次是关于柔软皮肤...
  17. yum安装php添加imap模块,php模块安装之imap
  18. 20189200余超 2018-2019-2 移动平台应用开发实践第九周作业
  19. 计算机主机前后,电脑cpu后面的字母是什么意思
  20. linux shell 判断一个文件是不是链接文件

热门文章

  1. 鸿蒙科学实验课,无字天书、人造雪等30个小实验玩出大科学
  2. 【2021软件创新实验室暑假集训,小白勿进
  3. 分享CSS3里box-shadow属性的使用方法,包括内阴影box-shadow:inset
  4. 团队作业第二次—项目选题报告(待就业六人组)
  5. 那些牛逼的外贸人是如何在领英上“抢走你的客户”?
  6. 【Kubernetes存储篇】StorageClass存储类动态生成PV详解
  7. linux 网络带宽测试工具 iperf
  8. js常用插件(二)之移动端手势利器hammer单双指操作
  9. sheetjs在使用中日期被自动转换问题
  10. Android最新版,恢复出厂设置