您现在的位置是:首页 > 文章详情

JDK的3个bug

日期:2018-12-04点击:307

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); //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<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 等其它能静态检查类型的库。 

原文链接:https://my.oschina.net/tommylemon/blog/2967187
关注公众号

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。

持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。

转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。

文章评论

共有0条评论来说两句吧...

文章二维码

扫描即可查看该文章

点击排行

推荐阅读

最新文章