著名的128陷阱---工作中踩得坑
阿新 • • 發佈:2020-12-14
本來已經寫過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。
List<AdminRolePermissionResponse> list1 = new ArrayList<>();
for (AdminPermission adminPermission : list) {
if(adminPermission.getRefPermissionId() == parentId){
/*業務程式碼*/
}
}
return list1;
}
我們看一下這句adminPermission.getRefPermissionId() == parentId,這裡我們使用的資料型別是Long型別,Long是long的包裝類和integer是一樣的性質,使用這種方法會有一個問題就是當資料大於128的時候會不走下面的業務程式碼導致資料丟失所以這裡應該改成equals。