JAVA中Long与Integer比较容易犯的错误

本文探讨了Java中比较Long和Integer对象的正确方法,并通过示例说明了在-128到127范围内数值的缓存机制。揭示了直接使用'=='可能导致的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

今天使用findbugs扫描项目后发现很多高危漏洞,其中非常常见的一个是比较两个Long或Integer时直接使用的==来比较。 其实这样是错误的。


因为Long与Ineger都是包装类型,是对象。 而不是普通类型long与int , 所以它们在比较时必须都应该用equals,或者先使用longValue()或intValue()方法来得到他们的基本类型的值然后使用==比较也是可以的。


但是有一种特殊情况, 其实Long与Integer都将 -128~127 这些对象缓存了。 可以看看Long类型源码里面有一个LongCache类,代码如下:

?
1
2
3
4
5
6
7
8
9
10
private 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 );
     }
     }

先看看这个例子:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
public 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));
     }
}
打印的结果是:

?
1
2
a == b ? true
c == d ? false

原因

首先来看看 Long a = 5L ; 它是如何将一个基本类型long包装成一个对象Long的 。

可以写一个测试类,然后反编译一下,看看java它是如何解析Long a = 5L这样一条命令的 。

测试类如下:

?
1
2
3
public class Test06 {
     Long l = 3L;
}
然后使用javap -verbose Test06 就能看到反编译的结果了, 下面是输出的部分:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
{
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>
从Code中的8可以看出调用了Long的一个类方法Long.valueOf(Long) , 所以可以得到的结论是Long a = 5L实际上等于 Long a = Long.valueOf(5) ;

然后再看看Long.valueOf()方法是如何定义的:

?
1
2
3
4
5
6
7
public 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);
   }
一目了然,会先判断基本类型的值如果在-128~127之间,就会直接从LongCache里面取出缓存的对象返回,否则就new一个新的Long对象返回 。


现在就不难理解Test05程序执行得到的结果了,因为a与b等于5,在-127~128之内,所以都是直接从LongCache里面返回的一个Long对象,所以他们在使用==比较的时候,就是相等的(对于对象类型来说,==比较的是两个对象的引用指向堆中的地址) ,而c与d等于129,不在-127~128之间,所以他们他们是分别new出来的两个新的Long对象,使用==来比较自然是不相等的了。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值