问题背景

我的天,最近做 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库,性能强势对比,另外 FastJson 也不建议用了,漏洞比较多。

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

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

推荐去我的博客阅读更多:

1.Java JVM、集合、多线程、新特性系列教程

2.Spring MVC、Spring Boot、Spring Cloud 系列教程

3.Maven、Git、Eclipse、Intellij IDEA 系列工具教程

4.Java、后端、架构、阿里巴巴等大厂最新面试题

觉得不错,别忘了点赞+转发哦!

我天!xx.equals(null) 是什么骚操作??的更多相关文章

  1. xxx==null和xxx.equals(null)的区别

    如果xxx不是null的话,xxx==null将返回false,如果xxx是null的话,xxx将返回ture 而对xxx.equals(null)而言,他将永远返回false,因为如果xxx不是nu ...

  2. Redis 数据结构之字符串的那些骚操作

    Redis 字符串底层用的是 sds 结构,该结构同 c 语言的字符串相比,其优点是可以节省内存分配的次数,还可以... 这样写是不是读起来很无聊?这些都是别人咀嚼过后,经过一轮两轮三轮的再次咀嚼,吐 ...

  3. Guava中这些Map的骚操作,让我的代码量减少了50%

    原创:微信公众号 码农参上,欢迎分享,转载请保留出处. Guava是google公司开发的一款Java类库扩展工具包,内含了丰富的API,涵盖了集合.缓存.并发.I/O等多个方面.使用这些API一方面 ...

  4. 闪电侠 Netty 小册里的骚操作

    前言 即使这是一本小册,但基于"不提笔不读书"的理念,仍然有必要总结一下.此小册对于那些"硬杠 Netty 源码 却不曾在千万级生产环境上使用实操"的用户非常有 ...

  5. Equal Sums (map的基本应用) 多学骚操作

    C. Equal Sums time limit per test 2 seconds memory limit per test 256 megabytes input standard input ...

  6. 关于MySQL的一些骚操作——提升正确性,抠点性能

    概要 回顾以前写的项目,发现在规范的时候,还是可以做点骚操作的. 假使以后还有新的项目用到了MySQL,那么肯定是要实践一番的. 为了准备,创建测试数据表(建表语句中默认使用utf8mb4以及utf8 ...

  7. 聊聊redis实际运用及骚操作

    前言 聊起 redis 咱们大部分后端猿应该都不陌生,或多或少都用过.甚至大部分前端猿都知道. 数据结构: string. hash. list. set (无序集合). setsorted(有序集合 ...

  8. C#中的9个“黑魔法”与“骚操作”

    C#中的9个"黑魔法"与"骚操作" 我们知道C#是非常先进的语言,因为是它很有远见的"语法糖".这些"语法糖"有时过于好 ...

  9. [C#.NET 拾遗补漏]05:操作符的几个骚操作

    阅读本文大概需要 1.5 分钟. 大家好,这是极客精神[C#.NET 拾遗补漏]专辑的第 5 篇文章,今天要讲的内容是操作符. 操作符的英文是 Operator,在数值计算中习惯性的被叫作运算符,所以 ...

随机推荐

  1. 使用Redis构建文章投票网站

    涉及到的key: 1. article_time, 记录文章的发布时间,zset结构 2. article_score, 记录文章的得分, zset结构 得分 = 发布时间 + 投票用户数 X 432 ...

  2. Python+Typora博客图片上传

    简介 用Typora 写Markdown 1年多了,这个编辑器的确很好用,但就是写完博客复制到博客园时要一个个手动插替换图片非常麻烦.后来发现最新版的Typora 已经支持图片上传功能,在 设置-图像 ...

  3. 【Hadoop离线基础总结】伪分布模式环境搭建

    伪分布模式环境搭建 服务规划 适用于学习测试开发集群模式 步骤 第一步:停止单节点集群,删除/export/servers/hadoop-2.7.5/hadoopDatas,重新创建文件夹 停止单节点 ...

  4. Spring Boot Admin简介及实践

    问题 在若干年前的单体应用时代,我们可以相对轻松地对整个业务项目进行健康检查.指标监控.配置管理等等项目治理.如今随着微服务的发展,我们将大型单体应用按业务模型进行划分,以此形成众多小而自治的微服务, ...

  5. js 调用webservice及nigix解决跨域问题

    前言 我们写一些简单的爬虫的时候会遇到跨域问题,难道我们一定要用后台代理去解决吗? 答案是否定的.python之所以适应爬虫,是因为库真的很好用. 好吧python不是今天的主角,今天的主角是js. ...

  6. ArrayList扩容机制实探

    ArrayList初始化 问题:执行以下代码后,这个list的列表大小(size)和容量(capacity)分别是多大? List<String> list = new ArrayList ...

  7. LeetCode寻找两个有序数组的中位数

    题目: 给定两个大小为 m 和 n 的有序数组 nums1 和 nums2. 请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n)). 你可以假设 nums1 和 nu ...

  8. [hdu3507 Print Article]斜率优化dp入门

    题意:需要打印n个正整数,1个数要么单独打印要么和前面一个数一起打印,1次打印1组数的代价为这组数的和的平方加上常数M.求最小代价. 思路:如果令dp[i]为打印前i个数的最小代价,那么有 dp[i] ...

  9. 10JAVA基础-常用类02

    Arrays 工具类,构造方法私有 //将数组转变为字符串 String str = Arrays.toString(int[] value); //对于原数组进行排序,升序 Arrays.sort( ...

  10. UEFI Shell --常用命令解释

    UEFI Shell解释 UEFI Shell 是一个提供用户和UEFI系统之间的接口,进入UEFI Shell可以对计算机系统进行配置 命令解释: 单独的help就可以输出所有指令,不做特殊说明,内 ...