0
点赞
收藏
分享

微信扫一扫

10年老鸟竟不知道Integer如何比较大小


前言

工作多年,最近在项目中一个地方Integer比较大小,竟然踩坑了。
那么你知道Integer比较大小的正确写法吗?

一、错误说明

先看一下下面这个demo,大家猜下,是相等还是不相等?

@Test
public void integerTest(){
Integer status = 1;

if("1".equals(status)){
System.out.println("相等");
}else{
System.out.println("不相等");
}
}

执行结果:

10年老鸟竟不知道Integer如何比较大小_缓存


原因分析:

equals方法的调用者“1”是一个字符串对象,所以这里走的是String对象的equals方法,而不是Integer对象的equals方法。

String对象的equals方法源码:

public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}

说明:
参数如果不是String类型,直接返回false。

二、优化一

那么正确写法是什么?

大部分人可能想到了Integer对象status前置,如下

@Test
public void integerTest2(){
Integer status = 1;
if(status.equals(1)){
System.out.println("相等");
}else{
System.out.println("不相等");
}
}

执行结果:

10年老鸟竟不知道Integer如何比较大小_新星计划_02


分析:

结果确实正确。但是大家有想过一点吗,由于程序中,Integer对象是可以为null的。一个为null的对象是不能调用任何方法的,否则就会出现空指针异常。

10年老鸟竟不知道Integer如何比较大小_新星计划_03

三、阿里规约的相关说明

这点大家应该都想到了String对象的等值比较,阿里的java规范中也提到的,尽量使用非空常量对象作为方法的调用方。

10年老鸟竟不知道Integer如何比较大小_新星计划_04

四、Integer等值比较优化

Integer等值比较优化

@Test
public void integerTest2(){
Integer status = null;
if(Integer.valueOf(1).equals(status)){
System.out.println("相等");
}else{
System.out.println("不相等");
}
}

执行结果:

10年老鸟竟不知道Integer如何比较大小_缓存_05


这样,即使变量status为空,也不会影响equals方法的比较结果。

五、相关建议

1、包装类型等值比较必须使用equals,只有基本类型等值比较使用==
2、调用equals方法时,使用常量和确定有值的对象作为方法的调用方,减少空指针异常。
3、进行equals等值判断的值,推荐采用常量类或枚举类进行封装。
4、偷懒的写法:Integer.valueOf(1).equals(status)。将基本类型转成包装类后再使用equals比较。

六、Integer的缓存说明

@Test
public void integerTest2(){
Integer integer1 = 3;
Integer integer2 = 3;
if(integer1 == integer2){
System.out.println("相等");
}else{
System.out.println("不相等");
}

integer1 = new Integer("3");
integer2 = new Integer("3");
if(integer1 == integer2){
System.out.println("相等");
}else{
System.out.println("不相等");
}

integer1 = 128;
integer2 = 128;
if(integer1 == integer2){
System.out.println("相等");
}else{
System.out.println("不相等");
}
}

执行结果:

相等
不相等
不相等

说明:
首先说明一点,Integer这个缓存机制,其实对我们写代码来说基本没什么影响,只是对底层数据存储的内存优化。
实际项目开发过程中,Integer的等值比较必须采用equals,而不能使用==。

执行结果说明:
由于==实际比较的是对象的内存地址,而Integer在-128 至 127 范围内采用Integer integer1 = 3这样的方式复制时,会复用已经缓存的对象,所以相等。

采用new的方式会重新声明对象会分配新的内存地址,不使用缓存对象,所以不相等。

超过128的对象不会使用缓存对象,地址都重新分配,所以不相等。

总结

1.包装类型等值比较必须使用equals,基本类型等值比较使用==

2.Integer的缓存范围在-128~127(默认),知道就好,项目中禁止使用 ==来比较Integer的大小。

3、基本类型需要转为包装类型再调用equals方法比较大小

Integer.valueOf(1).equals(status)

4、为了避免魔法值,对参与equals等值比较的值,尽量采用常量类或枚举类进行封装。


举报

相关推荐

0 条评论