前言
改一个别人的bug时遇到的,感觉有点意思。
问题
先看一段代码:
public static void main(String[] args) {
String sourceStr = "";
JSONObject jsonObject = JSONObject.parseObject(sourceStr);
System.out.println(jsonObject);
}
问:
- 当sourceStr为null的时候,会报空指针异常吗?
- 当sourceStr为空字符串的时候,会报解析异常吗?
- 当sourceStr为字符串"null"的时候,会报什么错误呢?
代码
public static void main(String[] args) {
String sourceStr = null;
JSONObject jsonObject = JSONObject.parseObject(sourceStr);
System.out.println(jsonObject);
sourceStr = "";
jsonObject = JSONObject.parseObject(sourceStr);
System.out.println(jsonObject);
sourceStr = "null";
jsonObject = JSONObject.parseObject(sourceStr);
System.out.println(jsonObject);
}
上面代码的输出结果:
null
null
null
总结
发现这个问题的原因是有个同事在对字符串判空的时候使用的是 if (str == null),但是传入的str是一个空字符串"", 所以后面对解析出来的jsonObject进行操作的时候就出现了空指针。其实现在有很多包中都有StringUtils这种工具类,里面有isEmpty()这种方法,整合了 (str == null) 和 str.length = 0,一般建议使用这种判空方法,当然也要结合具体的业务场景。
后记
其实我在找这个问题的时候正经花了比较大的功夫,因为中间有一些曲折。。。
先贴一下大致的代码:
class JsonUtils {
private static final Logger log = LoggerFactory.getLogger(JsonUtils.class);
public void test(String sourceStr) {
log.info("sourceStr: {}", sourceStr);
if (sourceStr == null) {
return;
}
JSONObject jsonObject = JSONObject.parseObject(sourceStr);
System.out.println(jsonObject.getString("a"));
}
}
从上面的代码可以看出,sourceStr是一个传参,我们并不知道它是什么,但是有log记录,同时也是这个log让我走了很长的弯路。
大致流程是这样的:
-- 发现jsonObject.getString("a") 出现空指针异常,猜测jsonObject为null;
-- 立即问了负责这块的同事,让他看一下日志中的sourceStr打印的是什么;
-- 同事回复的打印是: sourceStr: null;
-- 我就开始奇怪了,如果sourceStr是null的话,会直接return,不会走到下面空指针的地方呀;
-- 这个时候我的小脑袋瓜子不知道想到哪儿了,突然觉得难道传进来的是字符串"null"?
-- 我立即写了代码来验证我的猜想:
public static void main(String[] args) {
JsonUtils.test("null");
}
结果让我有点意料不到:
sourceStr: null
java.lang.NullPointerException
需要注意的是,log打印的时候,null和字符串 "null" 打印出来的结果是一毛一样的。
-- 难道真的是这个原因??
-- 后来和相关方确认,不可能会传一个字符串"null"进来,到这儿陷入了僵局
-- 于是我亲自去找了相应的日志,发现。。。。。。 告诉我sourceStr是null的那个同事看错日志的时间了。。。,他看到sourceStr为null的那些时候,根本就没有出现空指针异常。出现空指针异常的时候,传入的sourceStr为空字符串""
-- 问题解决。