JDK 的 3 个 bug

JDK 的 3 个 bug


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 {  // >  // >    public static final Map> ACCESS_MAP;  static { //注册权限        ACCESS_MAP = new HashMap>();    ACCESS_MAP.put(Verify.class.getSimpleName(), getAccessMap(Verify.class.getAnnotation(MethodAccess.class)));  }  public static HashMap getAccessMap(MethodAccess access) {    if (access == null) {      return null;    }    HashMap 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.JSONArrayarr.add("s");List list = new ArrayList<>(arr);list.get(0); //Exception cannot cast String to Long


解决方案:1.改用 Open JDK82.升级 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 类型的数据,get 出来赋值给 T 类型的变量/常量报错。

String json = "[1, '2', 'a']";Type type = new TypeToken(){}.getType();Gson gson = new Gson();List list = gson.fromJson(json, type);Integer i = list == null || list.isEmpty() ? null : list.get(1); //Exception cannot cast String to Integer


解决方案:1.手动检查列表内数据都符合泛型

T2.改用 fastjson等其它能静态检查类型的库。

所谓技多不压身,我们所读过的每一本书,所学过的每一门语言,在未来指不定都能给我们意想不到的回馈呢。其实做为一个开发者,有一个学习的氛围跟一个交流圈子特别重要这里我推荐一个Java学习交流群342016322,不管你是小白还是大牛欢迎入驻,大家一起交流成长。

你可能感兴趣的:(JDK 的 3 个 bug)