1. 程式人生 > 其它 >著名的128陷阱---工作中踩得坑

著名的128陷阱---工作中踩得坑

技術標籤:java基礎java

本來已經寫過128陷阱的部落格了,但是上週在實際開發的時候遇到了一個bug,然後自已眼看資料庫的id值,在128以前的資料是沒有問題的,但是在128以後的資料就會莫名的丟失。
首先讓我們看一小段程式碼:

    public static void main(String[] args) {
        Integer a = 127;
        Integer b = 127;
        Integer c = 128;
        Integer d = 128;
        System.out.println(a == b)
; System.out.println(c == d); }

來看看列印的結果:
在這裡插入圖片描述
這裡可以看出在int的包裝類Integer在127的時候是可以使用==去判斷兩個數是否相等的,而在Integer是128的時候就不能去判斷這兩個數是否相等。如果要問他的原因,讓我們讀一下原始碼:

    /**
     * Returns an {@code Integer} instance representing the specified
     * {@code int} value.  If a new {@code Integer} instance is not
     * required, this method should generally be used in preference to
     * the constructor {@link #Integer(int)}, as this method is likely
     * to yield significantly better space and time performance by
     * caching frequently requested values.
     *
     * This method will always cache values in the range -128 to 127,
     * inclusive, and may cache other values outside of this range.
     *
     * @param  i an {@code int} value.
     * @return an {@code Integer} instance representing {@code i}.
     * @since  1.5
     */
public static Integer valueOf(int i) { if (i >= IntegerCache.low && i <= IntegerCache.high) return IntegerCache.cache[i + (-IntegerCache.low)]; return new Integer(i); }

可以看下注釋註釋中也有說明,我們自己來看一下這個自動裝包的方法valueOf,IntegerCache.low和IntegerCache.high可以在上面程式碼定義中看到,定義的為-128和127,當然也可以通過程式碼得知,讀程式碼可知,如果這個數實在-128到127之間則直接返回這個已經定義在陣列中的值,而不再這個範圍中則需要去new一個新的物件,我們知道在java中==比較額是儲存物件的地址,在大於等於128的情況下他其實是new了兩個物件,他們的 == 判斷自然是不可取的,這裡我們要判斷應該是使用equals。

看一下實際開發中遇到的bug

        List<AdminRolePermissionResponse> list1 = new ArrayList<>();
        for (AdminPermission adminPermission : list) {
            if(adminPermission.getRefPermissionId() == parentId){
             	/*業務程式碼*/
            }
        }
        return list1;
    }

我們看一下這句adminPermission.getRefPermissionId() == parentId,這裡我們使用的資料型別是Long型別,Long是long的包裝類和integer是一樣的性質,使用這種方法會有一個問題就是當資料大於128的時候會不走下面的業務程式碼導致資料丟失所以這裡應該改成equals。