-
今天使用findbugs扫描项目后发现很多高危漏洞,其中非常常见的一个是比较两个Long或Integer时直接使用的==来比较。 其实这样是错误的。
因为Long与Ineger都是包装类型,是对象。 而不是普通类型long与int , 所以它们在比较时必须都应该用equals,或者先使用longValue()或intValue()方法来得到他们的基本类型的值然后使用==比较也是可以的。
但是有一种特殊情况, 其实Long与Integer都将 -128~127 这些对象缓存了。 可以看看Long类型源码里面有一个LongCache类,代码如下:
12345678910private
static
class
LongCache {
private
LongCache(){}
static
final
Long cache[] =
new
Long[-(-
128
) +
127
+
1
];
static
{
for
(
int
i =
0
; i < cache.length; i++)
cache[i] =
new
Long(i -
128
);
}
}
先看看这个例子:12345678910111213public
class
Test05 {
public
static
void
main(String[] args) {
Long a = 5L;
Long b = 5L;
System.out.println(
"a == b ? "
+ (a == b));
Long c = 129L;
Long d = 129L;
System.out.println(
"c == d ? "
+ (c == d));
}
}
12a == b ?
true
c == d ?
false
原因首先来看看 Long a = 5L ; 它是如何将一个基本类型long包装成一个对象Long的 。
可以写一个测试类,然后反编译一下,看看java它是如何解析Long a = 5L这样一条命令的 。
测试类如下:
123public
class
Test06 {
Long l = 3L;
}
123456789101112131415161718192021222324{
java.lang.Long l;
public
com.spring.test.Test06();
Code:
Stack=
3
, Locals=
1
, Args_size=
1
0
: aload_0
1
: invokespecial #
10
;
//Method java/lang/Object."<init>":()V
4
: aload_0
5
: ldc2_w #
12
;
//long 3l
8
: invokestatic #
14
;
//Method java/lang/Long.valueOf:(J)Ljava/lang/Long;
11
: putfield #
20
;
//Field l:Ljava/lang/Long;
14
:
return
LineNumberTable:
line
3
:
0
line
5
:
4
line
3
:
14
LocalVariableTable:
Start Length Slot Name Signature
0
15
0
this
Lcom/spring/test/Test06;
}</init>
然后再看看Long.valueOf()方法是如何定义的:
1234567public
static
Long valueOf(
long
l) {
final
int
offset =
128
;
if
(l >= -
128
&& l <=
127
) {
// will cache
return
LongCache.cache[(
int
)l + offset];
}
return
new
Long(l);
}
现在就不难理解Test05程序执行得到的结果了,因为a与b等于5,在-127~128之内,所以都是直接从LongCache里面返回的一个Long对象,所以他们在使用==比较的时候,就是相等的(对于对象类型来说,==比较的是两个对象的引用指向堆中的地址) ,而c与d等于129,不在-127~128之间,所以他们他们是分别new出来的两个新的Long对象,使用==来比较自然是不相等的了。
JAVA中Long与Integer比较容易犯的错误
最新推荐文章于 2023-10-19 23:55:28 发布