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

代码测试

public class IntegerTest {

public static void main(String[] args) {

Integer i1 = 127;

Integer i2 = 127;

System.out.println(i1 == i2);

Integer i3 = 128;

Integer i4 = 128;

System.out.println(i3 == i4);

}

}

以上代码的执行结果为:

true

false

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

public class IntegerTest {

public static void main(String[] paramArrayOfString) {

Integer integer1 = Integer.valueOf(127);

Integer integer2 = Integer.valueOf(127);

System.out.println((integer1 == integer2));

Integer integer3 = Integer.valueOf(128);

Integer integer4 = Integer.valueOf(128);

System.out.println((integer3 == integer4));

}

}

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

public static Integer valueOf(int i) {

if (i >= IntegerCache.low && i <= IntegerCache.high)

return IntegerCache.cache[i + (-IntegerCache.low)];

return new Integer(i);

}

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

private static class IntegerCache {

static final int low = -128;

static final int high;

static final Integer cache[];

static {

// high value may be configured by property

int 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_VALUE

h = 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 之间时,它会复用已有的对象,因此在 i1(127)和 i2 使用 == 对比时值才会为 true,而当取值变为 128 时,则执行的结果为 false。

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

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

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

注意事项

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

public class IntegerTest {

public static void main(String[] args) {

Integer i1 = new Integer(127);

Integer i2 = new Integer(127);

System.out.println(i1 == i2);

}

}

以上代码的执行结果为:

false

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

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

其他比较方式

compareTo

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

public final class Integer extends Number implements Comparable {

// 忽略其他内容

}

compareTo 的使用如下:

public class IntegerTest {

public static void main(String[] args) {

Integer i1 = new Integer(128);

Integer i2 = new Integer(128);

System.out.println(i1.compareTo(i2));

}

}

以上代码的执行结果为:

0

compareTo 的源码如下:

public int compareTo(Integer anotherInteger) {

return compare(this.value, anotherInteger.value);

}

public static int compare(int x, int y) {

return (x < y) ? -1 : ((x == y) ? 0 : 1);

}

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

直接运算

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

public class IntegerTest {

public static void main(String[] args) {

Integer i1 = new Integer(128);

Integer i2 = new Integer(128);

System.out.println((i1 – i2) == 0);

}

}

以上代码的执行结果为:

true

扩展知识:IntegerCache 值域修改

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

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

public class IntegerTest {

public static void main(String[] args) {

Integer i1 = 999;

Integer i2 = 999;

System.out.println(i1 == i2);

}

}

以上代码的执行结果为:

true

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

总结

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

互动话题

原文 

http://developer.51cto.com/art/202007/620382.htm

本站部分文章源于互联网,本着传播知识、有益学习和研究的目的进行的转载,为网友免费提供。如有著作权人或出版方提出异议,本站将立即删除。如果您对文章转载有任何疑问请告之我们,以便我们及时纠正。

PS:推荐一个微信公众号: askHarries 或者qq群:474807195,里面会分享一些资深架构师录制的视频录像:有Spring,MyBatis,Netty源码分析,高并发、高性能、分布式、微服务架构的原理,JVM性能优化这些成为架构师必备的知识体系。还能领取免费的学习资源,目前受益良多

转载请注明原文出处:Harries Blog™ » 漫画:Integer 竟然有 4 种比较方法?

赞 (0)
分享到:更多 ()

评论 0

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址