作者 _赖宝


Long或Integer时直接使用的==来比较。 其实这样是错误的。

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

Long与Integer都将 -128~127 这些对象缓存了。  可以看看Long类型源码里面有一个LongCache类,代码如下:

private static class LongCache {
	private LongCache(){}

	static final <span style="color: black; background-color: rgb(160, 255, 255);">Long</span> cache[] = new <span style="color: black; background-color: rgb(160, 255, 255);">Long</span>[-(-128) + 127 + 1];

	static {
	    for(int i = 0; i < cache.length; i++)
		cache[i] = new <span style="color: black; background-color: rgb(160, 255, 255);">Long</span>(i - 128);
	}
    }



先看看这个例子:

public class Test05 {

    public static void main(String[] args) {
        <span style="color: black; background-color: rgb(160, 255, 255);">Long</span> a = 5L;
        <span style="color: black; background-color: rgb(160, 255, 255);">Long</span> b = 5L;

        System.out.println("a == b ? " + (a == b));

        <span style="color: black; background-color: rgb(160, 255, 255);">Long</span> c = 129L;
        <span style="color: black; background-color: rgb(160, 255, 255);">Long</span> d = 129L;
        System.out.println("c == d ? " + (c == d));
    }
}


打印的结果是:

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



原因


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

java它是如何解析Long

测试类如下:

public class Test06 {
    <span style="color: black; background-color: rgb(160, 255, 255);">Long</span> l = 3L;
}


然后使用javap -verbose Test06 就能看到反编译的结果了, 下面是输出的部分:

{
<span style="color: black; background-color: rgb(255, 255, 102);">java</span>.lang.<span style="color: black; background-color: rgb(160, 255, 255);">Long</span> l;

public com.spring.test.Test06();
  Code:
   Stack=3, Locals=1, Args_size=1
   0:   aload_0
   1:   invokespecial   #10; //Method <span style="color: black; background-color: rgb(255, 255, 102);">java</span>/lang/Object."<init>":()V
   4:   aload_0
   5:   ldc2_w  #12; //<span style="color: black; background-color: rgb(160, 255, 255);">long</span> 3l
   8:   invokestatic    #14; //Method <span style="color: black; background-color: rgb(255, 255, 102);">java</span>/lang/<span style="color: black; background-color: rgb(160, 255, 255);">Long</span>.valueOf:(J)Ljava/lang/<span style="color: black; background-color: rgb(160, 255, 255);">Long</span>;
   11:  putfield        #20; //Field l:Ljava/lang/<span style="color: black; background-color: rgb(160, 255, 255);">Long</span>;
   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;


}


从Code中的8可以看出调用了 Long 的一个类方法 Long .valueOf( Long ) , 所以可以得到的结论是 Long  a = 5L实际上等于  Long  a =  Long .valueOf(5) ;

Long.valueOf()方法是如何定义的:

public static <span style="color: black; background-color: rgb(160, 255, 255);">Long</span> valueOf(<span style="color: black; background-color: rgb(160, 255, 255);">long</span> l) {
	final int offset = 128;
	if (l >= -128 && l <= 127) { // will cache
	    return LongCache.cache[(int)l + offset];
	}
        return new <span style="color: black; background-color: rgb(160, 255, 255);">Long</span>(l);
    }


一目了然,会先 判断 基本 类型 的值如果在-128~127之间,就会直接从LongCache里面取出缓存的对象返回,否则就new一个新的 Long 对象返回 。

Long对象,所以他们在使用==比较的时候,就是相等的(对于对象类型来说,==比较的是两个对象的引用指向堆中的地址) ,而c与d等于129,不在-127~128之间,所以他们他们是分别new出来的两个新的Long对象,使用==来比较自然是不相等的了。

Long重写了equals方法:

public boolean equals(Object obj) {
	if (obj instanceof <span style="color: black; background-color: rgb(160, 255, 255);">Long</span>) {
	    return value == ((<span style="color: black; background-color: rgb(160, 255, 255);">Long</span>)obj).longValue();
	}
	return false;
    }


它是先通过.longValue()方法获取 Long 对象的基本 类型long 的值之后再做比较的。



Long的比较,最好是使用equals来比较才能确保得到我们想要的结果。


Integer与Long一样,这里就不举例了。