文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

为什么说两个 Integer 数值之间不建议使用 “==” 进行比较

2024-12-02 20:14

关注

本文转载自微信公众号「Java极客技术」,作者鸭血粉丝Tang。转载本文请联系Java极客技术公众号。

众所周知阿里巴巴开发手册里面有一条强制的规则,说的是在包装类对象之间的值比较的时候需要使用 equals 方法,在 -128 和 127 之间的数值比较可以使用 ==,如下图所示。具体的原因相信大家都知道,虽然规则中提到 -128 和 127 之间的数值比较可以使用 ==,但是阿粉强烈建议你还是不要这样,包装类统一使用 equals,特别是如果有些数值是通过 API 或者 RPC 接口过来的,一定要注意。

我们看看下面的程序

  1. public class IntegerEqualTest { 
  2.  
  3.     public static void main(String[] args) { 
  4.  
  5.         Integer a = genA(); 
  6.         //Integer a = genB(); 
  7.         Integer b = 0; 
  8.         if (a == b) { 
  9.             System.out.println("a == 0"); 
  10.         } else { 
  11.             System.out.println("a != 0"); 
  12.         } 
  13.         System.out.println(a == b); 
  14.         System.out.println(a == 0); 
  15.     } 
  16.  
  17.     private static Integer genA() { 
  18.         return new Integer(0); 
  19.     } 
  20.  
  21.     private static Integer genB() { 
  22.         return 0; 
  23.     } 

大家可以先看下上面这一段代码,先猜测一下运行的结果是什么,如果再把 Integer a = genA(); 这行注释,Integer a = genB(); 这行放开,运行的结果又是什么。

好,1 2 3 结果如下所示

当我们替换注释那一行的时候,运行结果如下

看到这里其实很多小伙伴都知道是为什么,因为 genA() 方法里面是使用的 Integer 的构造器,构造的是一个新的对象,所以在使用 == 做对比的时候,比较的两个对象是不一样的。

是的,原因是这个,但是还有一点没说清楚那就是为什么在使用 genA() 的时候,下面的结果会不一样。

  1. System.out.println(a == b);//false 
  2.  System.out.println(a == 0);//true 

其实短短的几行代码里面,包含了好几个知识点,分别是自动装箱拆箱以及 Integer 的 -128 到 127 的数字缓存。

装箱拆箱

装箱:自动将基本数据类型转换为包装器类型;

拆箱:就是自动将包装器类型转换为基本数据类型。

在装箱的时候自动调用的是 Integer 的 valueOf(int) 方法。而在拆箱的时候自动调用的是 Integer 的 intValue方法。

上面的代码中 Integer b = 0; 会触发自动的装箱调用 Integer valueOf() 方法。而在使用 a == 0 这句的时候,会触发自动的拆箱。然后我们看源码会发现有下面缓存的逻辑,其中 IntegerCache.low 是 -128,IntegerCache.high 默认是 127,不过可以通过 JVM 参数进行配置。我们这里的代码是 0,所以会从缓存中获取。

  1. public static Integer valueOf(int i) { 
  2.     if (i >= IntegerCache.low && i <= IntegerCache.high) 
  3.         return IntegerCache.cache[i + (-IntegerCache.low)]; 
  4.     return new Integer(i); 

为了充分说明 Integer 的缓存,我们看下下面这段程序的执行结果

  1. Integer c1 = 128; 
  2. Integer c2 = 128; 
  3. System.out.println(c1 == c2); 

在运行之前我们先自己分析一下,首先 Integer c1 = 128 和 Integer c2 = 128 按照我们上面说的,会触发自动装箱调用 valueOf 方法,通过 valueOf源码我们可以看到在默认的情况下 128 已经不再 Integer 的缓存里面了,所以 if 条件不满足会通过 new Integer 构造方法创建两个对象,所以最终的结果应该是输出 false。

下面再说一下为什么说在 -128 和 127 以内的也不建议直接使用 == 来实现比较,很显然就跟我们上面的genA() 方法一样,很多时候不会一下子就知道一个方法值是怎么得到,即使是缓存范围以内,别人也有可能是通过构造函数创建出来的,这样我们在做比较的时候很有可能就会跟预期的不一样,从而产生事故。

 

特别是如果通过 RPC 接口获得返回结果,我们可能连别人的实现方式压根就看不到,更没办法提前知道了。所以我们还是老老实实的按照阿里巴巴的 Java 规范来编写代码,采用equals 方法来判断,这样肯定没问题。

 

来源:Java极客技术内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯