1.Annotation引用非空enum數組返回空數組
首次發現時的環境:JDK 1.8
首次發現所在項目:APIJSON
測試用例:
public enum RequestRole {
/**未登錄,不明身份的用戶
*/
UNKNOWN,
/**已登錄的用戶
*/
LOGIN,
/**聯繫人,必須已登錄
*/
CONTACT,
/**圈子成員(CONTACT + OWNER),必須已登錄
*/
CIRCLE,
/**擁有者,必須已登錄
*/
OWNER,
/**管理員,必須已登錄
*/
ADMIN;
//似乎不管怎麼做,外部引用後都是空值。並且如果在註解內的位置不是最前的,還會導致被註解的類在其它類中import報錯。
//雖然直接打印顯示正常,但被@MethodAccess內RequestRole[] GET()等方法引用後獲取的是空值
public static final RequestRole[] ALL = {RequestRole.UNKNOWN};//values();//所有
public static final RequestRole[] HIGHS;//高級
static {
HIGHS = new RequestRole[] {OWNER, ADMIN};
}
public static final String[] NAMES = {
UNKNOWN.name(), LOGIN.name(), CONTACT.name(), CIRCLE.name(), OWNER.name(), ADMIN.name()
};
}
@MethodAccess(
GETS = RequestRole.ALL,
HEADS = RequestRole.HIGHS
)
public class Verify {
}
public class DemoVerifier {
// <TableName, <METHOD, allowRoles>>
// <User, <GET, [OWNER, ADMIN]>>
public static final Map<String, Map<RequestMethod, RequestRole[]>> ACCESS_MAP;
static { //註冊權限
ACCESS_MAP = new HashMap<String, Map<RequestMethod, RequestRole[]>>();
ACCESS_MAP.put(Verify.class.getSimpleName(), getAccessMap(Verify.class.getAnnotation(MethodAccess.class)));
}
public static HashMap<RequestMethod, RequestRole[]> getAccessMap(MethodAccess access) {
if (access == null) {
return null;
}
HashMap<RequestMethod, RequestRole[]> map = new HashMap<>();
map.put(GET, access.GET());
map.put(HEAD, access.HEAD());
map.put(GETS, access.GETS());
map.put(HEADS, access.HEADS());
map.put(POST, access.POST());
map.put(PUT, access.PUT());
map.put(DELETE, access.DELETE());
return map;
}
}
解決方案:
不抽象數組常量ALL,HIGHTS等,而是在每個用到的地方硬編碼寫死具體的值。
2.ArrayList可通過構造函數傳入非指定泛型的List並在get時出錯
首次發現時的環境:JDK 1.7
首次發現所在項目:APIJSON
測試用例:
JSONArray arr = new JSONArray(); //com.alibaba.fastjson.JSONArray
arr.add("s");
List<Long> list = new ArrayList<>(arr);
list.get(0); //throw new IllegalArgumentException
解決方案:
1.改用 Open JDK8
2.升級 JDK
注:後面多次測試,已無法復現。
3.基本類型在三元表達式內可賦值爲null,編譯通過但運行出錯
首次發現時的環境: JDK 1.7
測試用例:
int i = true ? null : 0; //Exception in thread "main" java.lang.NullPointerException
首次發現所在項目:ZBLibrary
解決方案:
在給基礎類型用3元表達式賦值時,null 先轉爲基礎類型的默認值。
最後再提2個不是bug,但容易引發編程bug的問題:
1.局部變量和同名的全局變量能在一個方法內,編譯通過,運行也正常。
public class Test {
int val;
@Override
public String toString() {
val = 1;
String val = "";
return super.toString();
}
}
如果兩個變量中間隔了比較長的其它代碼,很可能會導致開發人員將兩者混淆,導致邏輯認知錯誤,從而寫出或改出有問題的代碼。
解決方案:
命名局部變量前先搜素,確保沒有已聲明的同名全局變量。
2. (非 JDK bug)Gson 通過 TypeToken 轉換 List<T> 能寫入不屬於 T 類型的數據,get 出來賦值給 T 類型的變量/常量報錯。
String json = "[1, '2', 'a']";
Type type = new TypeToken<Integer>(){}.getType();
Gson gson = new Gson();
List<Integer> list = gson.fromJson(json, type);
Integer i = list == null || list.isEmpty() ? null : list.get(1); //Exception cannot cast String to Integer
解決方案:
1.手動檢查列表內數據都符合泛型 T
2.改用 fastjson 等其它能靜態檢查類型的庫。