查看原文
其他

我天!xx.equals(null) 是什么骚操作??

栈长 Java技术栈 2020-12-28

Java技术栈

www.javastack.cn

打开网站看更多优质文章


问题背景

我的天,最近做 Code Review 看到一个同事的骚操作,他写了一个工具类,大概是这样的:

public static boolean isNull(Object object){
    return null == object || object.equals(null);
}

判断空,一般不是 null == object 就够了,object.equals(null) 是什么骚操作?

写程序这么多年,第一次看这样的写法,当时我就提出质疑了,同事拍着胸脯和我说,有个银行的请求参数必须得这么写,不然就验证不了。

我当时还在想,这是 JDK 出的什么新类型么,觉得还是不科学,考虑去跟下同事写的代码,然后用他所说的情况我亲自去验证一下。

看了下,这是个老业务系统,同事用了 json-lib 这个包,历史的江湖确实有这个包的存在,栈长之前也用过,不过后来这玩意就没怎么用了,现在都是 GsonJackson 的天下了。

如下面 json-lib 例子所示:

public static void main(String[] args) {
    String jsonString = "{\"name\": \"hi\",\"sex\": \"boy\", \"age\": null}";

    JSONObject jsonObject = net.sf.json.JSONObject.fromObject(jsonString);
    Object age = jsonObject.get("age");

    // 输出:null
    System.out.println("age: " + age);

    // 输出:false
    System.out.println("age == null: " + (age == null));

    // 输出:true
    System.out.println("age.equals(null): " + (age.equals(null)));
}

我天!大家看到结果了吧,问题确实也如同事所说,一定要用 object.equals(null) 写法才行,不相信结果的大家也可以亲自验证一下。

纳了闷了,这样写,我传一个 null 值过去不是报空指针了么?这样写肯定有问题,继续深挖!

问题分析

fromObject 方法加载 JSON 串开始源码深入分析,找到了这个神奇解析 null 值的源码:

原来,JSON 串中的 null 值被解析成了它内部的 JSONNull 对象,然后再看下这个 JSONNull 的 equals 方法源码:

public boolean equals(Object object) {
    return object == null || 
           object == this || 
           object == instance || 
           object instanceof JSONObject &&
           ((JSONObject)object).isNullObject() ||
           "null".equals(object);
}

问题就出在他所用的 JSON 工具类了!!!

equals 方法被重写了……终于揭开了 object.equals(null) 的神秘面纱……

再来看下是否有新的更新包:

最新的版本停留在 2010 年 12 月,已经是被淘汰的东西了。

另外,json-lib 在 JDK 1.7+ 有性能影响。
推荐阅读:请不要在 JDK 7+ 中使用这个 JSON 包了

解决方案

方法1:

换掉 object.equals(null),用 JSONNull 的实例去判断:

public static boolean isNull(Object object){
    return null == object || JSONNull.getInstance().equals(object);
}

方法2:

换掉 json-lib 库,用主流的  GsonJackson,具体看下这篇:Java常用的几个Json库,性能强势对比Json-lib 真不建议用了,另外 FastJson 也不建议用,漏洞比较多。

这个由于是老系统,太多业务使用了这个库,换掉的开发、测试成本和风险比较大,暂时考虑先用方案1先解决这个问题。

关注Java技术栈微信公众号,栈长将继续分享好玩的 Java 技术,公众号第一时间推送,在公众号后台回复:Java,可以获取历史 Java 教程,都是干货。

最近热文:

1、Java 14 祭出神器,Lombok 被干掉了?

2、一周面试了 30 人,面到我心态爆炸…
3、用 float 存储金额,老板说损失从工资扣!
4、阿里发布《Java开发手册(泰山版)》
5、推荐一款 IDEA 代码神器,再也不加班了!
6、Spring Boot Banner 换成了美女背景后…
7、Spring Boot 2.3 优雅关闭新姿势,真香!
8、Redis 到底是单线程还是多线程?
9、程序员面试 10 大潜规则,千万不要踩坑!
10、Struts2 为什么被淘汰?自己作死!
扫码关注Java技术栈公众号阅读更多干货。

点击「阅读原文」带你飞~

    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存