关于Java 中Integer 和Long对象 对比的陷阱(简单却容易犯的错误)

彩票客户端“忘记密码”功能有bug,今天调试时,发现了原因:

 

功能模块中有一段:

 

if(userpo.getId()!=Long.valueOf(uid)){

throw new VerifyException("mobile have been binded for uid=" + uid ,

    AppCode.VERIFY_MOBILE_IS_BIND);

}

 

问题就处在两个Long型对象的比较。

 

情景:

userpo.getId()返回一个Long型对象,值是10027

Long.valueOf(uid)返回一个Long型对象,值也是10027

 

但是他们 != 运算的值是 true java对象对比一般都使用 equals 方法或者compareTo方法

 

解决方案:

 

以上代码应该改成:userpo.getId().equals(Long.valueOf(uid)返回 true

 

猜想:

 

当初代码肯定是通过测试的,那当初是为什么会通过测试?因为最初数据小。

 

思考:

 

值得注意的是,最初学java时,我印象中IntegerLong类型的对象有使用过 == != 这样来比较,结果好像也对过。

 

其实确实有一种情况使用 == != 这样来比较也对。

 

例如我写了一个测试类测试IntegerLong类型对象的比较:

 

public class Test {

public static void main(String[] args) {

Integer a = new Integer(10);

Integer b = new Integer(10);

System.out.println("a==b:" + (a==b)); //很明显false

Integer c = 129;

Integer d = 129;

System.out.println("c==d:" + (c==d)); //false

Integer e = 127;

Integer f = 127;

System.out.println("e==f:" + (e==f));//true

Long h = 128L;

Long g = 128L;

System.out.println("h==g:" + (h==g));//false

System.out.println("h.equals(g):" + h.equals(g));//true

System.out.println("h.compareTo(g):" + h.compareTo(g));// 0

Long k = 127L;

Long m = 127L;

System.out.println("k==m:" + (k==m));//true

 

System.out.println("k.equals(m):" + k.equals(m));//true

System.out.println("k.compareTo(m):" + k.compareTo(m));//0

}

}

 

执行结果:

a==b:false

c==d:false

e==f:true

h==g:false

h.equals(g):true

h.compareTo(g):0

k==m:true

k.equals(m):true

k.compareTo(m):0

 

原因:查看Integer源代码后发现Integer有个内部类IntegerCache,它维护了一个Integer数组cache[] ,长度为256,还有一个静态块

 

static {

      for(int i = 0; i < cache.length; i++)

         cache[i] = new Integer(i - 128);

}

 

很明显这个静态块已经默认认创建出了-128~127 的 Integer 数据,因此Integer在创建对象时,若值在(-128到127)范围内,则直接从缓冲区中取,若超过该范围则创建新对象,因此在-128到127范围内Integer对象值相同时,对象  ==返回true

 

Long对象同理。

 

注:内容结合了网络的一些解答。

posted @ 2013-09-18 11:51  Hassan Blog  阅读(2274)  评论(0编辑  收藏  举报