未分类

数据的相等性比较引发的 BUG

问题

相同的代码逻辑,在不同的环境得出了不同的结果。在业务系统里是正确的,但是数据系统里却计算出了不同的结果。给一个示例:

1
2
3
4
5
Integer x = 1234567;
Long y = 1234567L;
if (x.equals(y))) {
// 处理业务逻辑
}

我们预期if语句判断能够成功并进入进行处理业务逻辑,但实际上这里会始终返回 false。这是因为java.lang.Integerjava.lang.Longequals方法实现均会先判断类型,类型相同才会进行实际的相等性比较。Integer#equals方法实现如下:

1
2
3
4
5
6
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}

怎样避免此类问题?

配置 IDEA 提升对于不兼容类型进行相等性比较时的检查级别

两个不兼容类型的相等性比较

1
2
3
4
5
6
7
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="EqualsBetweenInconvertibleTypes" enabled="true" level="ERROR" enabled_by_default="true" editorAttributes="ERRORS_ATTRIBUTES" />
</profile>
</component>

Java 17

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|  Welcome to JShell -- Version 17.0.6
| For an introduction type: /help intro

jshell> var i = new Integer(12345678)
| Warning:
| Integer(int) in java.lang.Integer has been deprecated and marked for removal
| var i = new Integer(12345678);
| ^-------------------^
i ==> 12345678

jshell> Integer i = 12345678;
i ==> 12345678

jshell> Long l = 12345678L;
l ==> 12345678

jshell> i.equals(i, l)
| Error:
| method equals in class java.lang.Integer cannot be applied to given types;
| required: java.lang.Object
| found: java.lang.Integer,java.lang.Long
| reason: actual and formal argument lists differ in length
| i.equals(i, l)
| ^------^

jshell> Objects.equals(i, l)
$4 ==> false

jshell> i == l
| Error:
| incomparable types: java.lang.Integer and java.lang.Long
| i == l
| ^----^

其它语言

Scala

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
(base) ➜  spring3-template git:(main) ✗ scala
Welcome to Scala 3.2.1 (17.0.6, Java OpenJDK 64-Bit Server VM).
Type in expressions for evaluation. Or try :help.

scala> val i = new java.lang.Integer(12345678)
there was 1 deprecation warning; re-run with -deprecation for details
1 warning found
val i: Integer = 12345678

scala> val l = new java.lang.Long(12345678)
there was 1 deprecation warning; re-run with -deprecation for details
1 warning found
val l: Long = 12345678

scala> i.equals(l)
val res0: Boolean = false

scala> java.util.Objects.equals(i, l)
val res1: Boolean = false

scala> i == l
val res2: Boolean = true

Rust

总结

TODO

分享到