前言
改一個別人的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為空字符串""
-- 問題解決。