漫画:Integer 竟然有 4 种比较方法?

开发 前端
在 Integer 的取值在 -128 到 127 之间时,它会复用已有的对象,因此在 i1(127)和 i2 使用 == 对比时值才会为 true,而当取值变为 128 时,则执行的结果为 false。

 本文转载自微信公众号「Java中文社群」,作者磊哥 。转载本文请联系 Java中文社群公众号。

 

 

 

 

代码测试

  1. public class IntegerTest { 
  2.     public static void main(String[] args) { 
  3.         Integer i1 = 127; 
  4.         Integer i2 = 127; 
  5.         System.out.println(i1 == i2); 
  6.         Integer i3 = 128; 
  7.         Integer i4 = 128; 
  8.         System.out.println(i3 == i4); 
  9.     } 

以上代码的执行结果为:

  1. true 
  2. false 

 

首先,当我们将以上的测试代码编译为字节码(.class)之后,编码的代码如下:

  1. public class IntegerTest { 
  2.   public static void main(String[] paramArrayOfString) { 
  3.     Integer integer1 = Integer.valueOf(127); 
  4.     Integer integer2 = Integer.valueOf(127); 
  5.     System.out.println((integer1 == integer2)); 
  6.     Integer integer3 = Integer.valueOf(128); 
  7.     Integer integer4 = Integer.valueOf(128); 
  8.     System.out.println((integer3 == integer4)); 
  9.   } 

可以看出在创建 Integer 时使用到了 valueOf,它的实现源码如下:

  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); 

从上述源码中可以看出这个方法中使用了 IntegerCache,IntegerCache 的源码如下:

  1. private static class IntegerCache { 
  2.     static final int low = -128; 
  3.     static final int high; 
  4.     static final Integer cache[]; 
  5.  
  6.     static { 
  7.         // high value may be configured by property 
  8.         int h = 127; 
  9.         String integerCacheHighPropValue = 
  10.             sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high"); 
  11.         if (integerCacheHighPropValue != null) { 
  12.             try { 
  13.                 int i = parseInt(integerCacheHighPropValue); 
  14.                 i = Math.max(i, 127); 
  15.                 // Maximum array size is Integer.MAX_VALUE 
  16.                 h = Math.min(i, Integer.MAX_VALUE - (-low) -1); 
  17.             } catch( NumberFormatException nfe) { 
  18.                 // If the property cannot be parsed into an intignore it. 
  19.             } 
  20.         } 
  21.         high = h; 
  22.  
  23.         cache = new Integer[(high - low) + 1]; 
  24.         int j = low; 
  25.         for(int k = 0; k < cache.length; k++) 
  26.             cache[k] = new Integer(j++); 
  27.  
  28.         // range [-128, 127] must be interned (JLS7 5.1.7) 
  29.         assert IntegerCache.high >= 127; 
  30.     } 
  31.  
  32.     private IntegerCache() {} 

从上述源码可以看出,在 Integer 的取值在 -128 到 127 之间时,它会复用已有的对象,因此在 i1(127)和 i2 使用 == 对比时值才会为 true,而当取值变为 128 时,则执行的结果为 false。

这一点其实在阿里巴巴的《Java开发手册》中也有相应的规定,规定的内容如下:

【强制】所有整型包装类对象之间值的比较,全部使用 equals 方法比较。

说明:对于 Integer var = ? 在 -128 至 127 之间的赋值,Integer 对象是在 IntegerCache.cache 产生, 会复用已有对象,这个区间内的 Integer 值可以直接使用 == 进行判断,但是这个区间之外的所有数据,都 会在堆上产生,并不会复用已有对象,这是一个大坑,推荐使用 equals 方法进行判断。

注意事项

不仅如此,当我们使用 new Integer 时,无论值为多少都不能使用 == 比较,示例代码如下:

  1. public class IntegerTest { 
  2.     public static void main(String[] args) { 
  3.         Integer i1 = new Integer(127); 
  4.         Integer i2 = new Integer(127); 
  5.         System.out.println(i1 == i2); 
  6.     } 

以上代码的执行结果为:

  • false

这是因为 new Integer 方法并没有使用到 IntegerCache,而是直接创建了新对象,因此就不能用 == 比较了。

小贴士:== 是用来直接比对两个对象的引用是否相同的,而 equals 则是用来对比两个对象的值是否相同的。

 

其他比较方式

compareTo

因为 Integer 类实现了 Comparable 接口,因此我们可以使用 compareTo 来对比两个值的大小,实现源码如下:

  1. public final class Integer extends Number implements Comparable<Integer> { 
  2.  // 忽略其他内容 

compareTo 的使用如下:

  1. public class IntegerTest { 
  2.     public static void main(String[] args) { 
  3.         Integer i1 = new Integer(128); 
  4.         Integer i2 = new Integer(128); 
  5.         System.out.println(i1.compareTo(i2)); 
  6.     } 

以上代码的执行结果为:

  • 0

compareTo 的源码如下:

  1. public int compareTo(Integer anotherInteger) { 
  2.     return compare(this.value, anotherInteger.value); 
  3. public static int compare(int x, int y) { 
  4.     return (x < y) ? -1 : ((x == y) ? 0 : 1); 

由此可以看出 compareTo 的返回值总共有三个:-1、0、1,其中 -1 表示前一值小于后一个值;0 表示两个值相等;1 表示前一个值大于后一个值,因此我们用它来比较两个 Integer 的值是否相等。

直接运算

compareTo 方法给我们了一个启发,我们可以直接将两个值进行相减,如果相减的值等于 0,则说明对比的两个值是相同的,示例代码如下:

  1. public class IntegerTest { 
  2.     public static void main(String[] args) { 
  3.         Integer i1 = new Integer(128); 
  4.         Integer i2 = new Integer(128); 
  5.         System.out.println((i1 - i2) == 0); 
  6.     } 

以上代码的执行结果为:

  • true

扩展知识:IntegerCache 值域修改

IntegerCache 默认的取值范围为 -128 到 127,但我们可以通过设置启动参数来调整 IntegerCache 的最大缓存值,比如我们可以配置虚拟机的启动参数 -XX:AutoBoxCacheMax=1000,此配置表示将缓存的最大值设置为 1000,如果是 Idea 的配置如下:

 

 

此时我们编写一个测试代码:

  1. public class IntegerTest { 
  2.     public static void main(String[] args) { 
  3.         Integer i1 = 999; 
  4.         Integer i2 = 999; 
  5.         System.out.println(i1 == i2); 
  6.     } 

以上代码的执行结果为:

  • true

从运行的结果可以看出 IntegerCache 的取值范围被成功的更改了。

总结

本文我们介绍了 Integer 的四种比较方式:==、equals、compareTo、直接运算,而 == 方式并不能用于 Integer 的比较,它只适用于非 new Integer 的一定范围内(-128~127),而后三种方式都可以正常用于 Integer 的比较,其中 equals 的比较方式是最简单也是最通用的。

 


原文链接:https://mp.weixin.qq.com/s/b9D_iaxX6SrNrw3WO55nVw

 

责任编辑:武晓燕 来源: Java中文社群
相关推荐

2021-07-05 18:05:40

SpringBean方法

2022-02-14 12:04:43

前缀SpringJpa

2020-11-03 06:57:10

MyBatis数据库

2019-09-18 15:20:16

MyBatisSQL数据库

2020-11-27 09:16:21

BlockingQue

2022-09-04 12:43:03

算法裁员Meta

2019-06-14 08:48:46

Tomcat日志SpringBoot

2015-07-20 15:26:56

WiFi感知

2021-12-08 08:30:55

Java AQS机制 Java 基础

2021-05-07 05:34:25

Windows10操作系统微软

2009-04-13 09:09:53

WebServices返回数据横向

2016-06-07 09:23:05

浏览器技巧快捷键

2021-02-03 20:19:08

Istio流量网格

2017-03-07 17:45:42

Windows磁盘碎片整理

2018-06-15 14:28:36

华为云

2020-11-02 08:35:59

内存数据库Redis

2021-06-10 09:00:33

单例模式数据库

2018-09-11 08:05:44

千兆路由器厂商

2011-08-01 14:54:24

编程语言

2012-10-16 09:40:38

洗牌算法
点赞
收藏

51CTO技术栈公众号