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, >
  //<User, >
    public static final Map<String, Map> ACCESS_MAP;
  static { //注册权限
        ACCESS_MAP = new HashMap<String, Map>();
    ACCESS_MAP.put(Verify.class.getSimpleName(), getAccessMap(Verify.class.getAnnotation(MethodAccess.class)));
  }

  public static HashMapgetAccessMap(MethodAccess access) {
    if (access == null) {
      return null;
    }

    HashMapmap = 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");

Listlist = new ArrayList<>(arr);
list.get(0); //Exception cannot cast String to Long

解决方案:

  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

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

解决方案:

  1. 手动检查列表内数据都符合泛型 T。

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

JDK 的 3 个 Bug,看这篇就对了!_JDK