天天看點

JAVA中Long與Integer踩的坑

 前幾天在項目上看到代碼2個Long型變量判斷是否相等用的是==,代碼在測試環境部署測試沒有問題,放到預發環境就有問題,于是就在main進行了如下測試

public class TestDemo {

    public static void main(String args[]){
        Long a=50L;
        Long b=50L;
        Long c=5000l;
        Long d=5000l;
        Long e=new Long(18);
        Long f=new Long(18);
        System.out.println(a==b);
        System.out.println(c==d);
        System.out.println(e==f);
        System.out.println(e.equals(f));
    }

}      
true
false
false
true


Process finished with exit code 0      

從代碼運作結果來看判斷Long型變量不能用==,隻能用equal,那麼就分析下原因:

1首先我們把一個long型數值賦予給了Long對象,這個過程其實就是基本類型到包裝類到封裝,Java上叫做裝箱,其實就是Long對象調用Long.valueOf(long) 的操作

2那麼點進去Long.valueOf(long)的源碼

/**
 * Returns a {@code Long} instance representing the specified
 * {@code long} value.
 * If a new {@code Long} instance is not required, this method
 * should generally be used in preference to the constructor
 * {@link #Long(long)}, as this method is likely to yield
 * significantly better space and time performance by caching
 * frequently requested values.
 *
 * Note that unlike the {@linkplain Integer#valueOf(int)
 * corresponding method} in the {@code Integer} class, this method
 * is <em>not</em> required to cache values within a particular
 * range.
 *
 * @param  l a long value.
 * @return a {@code Long} instance representing {@code l}.
 * @since  1.5
 */
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的時候從JVM緩存取出值,否則就new一個新對象,這就是我們用==判斷會出問題的原因

3我們用equal為啥可以,我們看看Long對象的equals方法

/**
 * Compares this object to the specified object.  The result is
 * {@code true} if and only if the argument is not
 * {@code null} and is a {@code Long} object that
 * contains the same {@code long} value as this object.
 *
 * @param   obj   the object to compare with.
 * @return  {@code true} if the objects are the same;
 *          {@code false} otherwise.
 */
public boolean equals(Object obj) {
    if (obj instanceof Long) {
        return value == ((Long)obj).longValue();
    }
    return false;
}      

由代碼可以看出,用equal判斷,Long會自動調用longValue()方法後再對比

可見還是要養成多看看源碼的好習慣!