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);
}
}
复制代码
以上代码的执行结果为:java
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
,它的实现源码以下:this
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。spa
这一点其实在阿里巴巴的《Java开发手册》中也有相应的规定,规定的内容以下:3d
【强制】全部整型包装类对象之间值的比较,所有使用 equals 方法比较。code
说明:对于 Integer var = ? 在 -128 至 127 之间的赋值,Integer 对象是在 IntegerCache.cache 产生, 会复用已有对象,这个区间内的 Integer 值能够直接使用 == 进行判断,可是这个区间以外的全部数据,都 会在堆上产生,并不会复用已有对象,这是一个大坑,推荐使用 equals 方法进行判断。orm
不只如此,当咱们使用 new Integer 时,不管值为多少都不能使用 == 比较,示例代码以下:cdn
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 则是用来对比两个对象的值是否相同的。
由于 Integer 类实现了 Comparable 接口,所以咱们可使用 compareTo 来对比两个值的大小,实现源码以下:
public final class Integer extends Number implements Comparable<Integer> {
// 忽略其余内容
}
复制代码
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 的返回值总共有三个:-一、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
咱们可使用 intValue 获得 Integer 的 int 值,而后再使用 == 进行比较,示例代码以下:
public class IntegerTest {
public static void main(String[] args) {
Integer i = 558;
Integer i2 = 558;
System.out.println(i.intValue() == i2.intValue());
}
}
复制代码
以上代码的执行结果为:
true
异或是一个数学运算符,它应用于逻辑运算。在计算机中若是 a、b 两个值不相同,则异或结果为 1;若是 a、b 两个值相同,异或结果为 0。
好比:
异或实现示例以下:
public class IntegerTest {
public static void main(String[] args) {
Integer i = 558;
Integer i2 = 558;
System.out.println((i ^ i2) == 0);
}
}
复制代码
以上代码的执行结果为:
true
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 的 6 种比较方式:==、equals、compareTo、直接运算,而 == 方式并不能用于 Integer 的比较,它只适用于非 new Integer 的必定范围内(-128~127),然后 5 种方式均可以正经常使用于 Integer 的比较,其中 equals 的比较方式是最为经常使用的。
除了以上几种比较方式以外,你还知道其余的比较方式吗?欢迎评论区补充留言。
关注公众号「Java中文社群」订阅更多精彩。