詳解Spring的StringUtils踩坑記錄
起因
最近在寫CRUD的時(shí)候,發(fā)現(xiàn)有個(gè)分頁(yè)的VO寫的健壯性比較差,一時(shí)手癢改了一下,沒(méi)想到改了之后好幾個(gè)功能都出現(xiàn)了問(wèn)題。
原VO關(guān)鍵代碼如下:
public class PageVo implements Serializable{
// ...省略所有無(wú)關(guān)代碼
Map<String, String> query
}
這個(gè)VO是用于從前端分頁(yè)查詢時(shí)傳參,而query是用于傳遞查詢條件的(這里不討論用Map傳參是否合理)。當(dāng)前端無(wú)查詢條件時(shí)則會(huì)導(dǎo)致query為null,如果不注意容易出現(xiàn)NPE。
所以我就改造成下面這樣了。
public class PageVo implements Serializable{
// ...省略所有無(wú)關(guān)代碼
Map<String, String> query=new HashMap<>
}
但是沒(méi)想到就是這么簡(jiǎn)單的改造居然都翻車(・ε・`)
沒(méi)辦法,只好去排查問(wèn)題。
發(fā)現(xiàn)問(wèn)題
想過(guò)很多種原因,但是我真沒(méi)想到居然是因?yàn)檫@樣(/‵Д′)/~ ╧╧,不多說(shuō)了,問(wèn)題關(guān)鍵代碼如下:
if (StringUtils.isEmpty(page.getQuery())) {
// 省略處理邏輯
}
居然用StringUtils去判斷一個(gè)Map是否為空,好歹也換個(gè)CollectionUtils啊(╬ ̄皿 ̄)凸
雖然是前人挖坑,但是為什么Spring的`StringUtils居然設(shè)計(jì)成支持Object入?yún)⒛豲_o ....
想了一下,還是去看看源碼吧
源碼分析
StringUtils的isEmpty()方法源碼超級(jí)簡(jiǎn)單,三行代碼搞定(其實(shí)嚴(yán)格來(lái)說(shuō)就一行代碼):
public static boolean isEmpty(@Nullable Object str) {
return (str == null || "".equals(str));
}
既然我的Map對(duì)象不為null,那么問(wèn)題應(yīng)該是因?yàn)镾tring的equals()方法。不多說(shuō),繼續(xù)跟蹤源碼
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
// 問(wèn)題出在這里
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
這個(gè)equals()方法的邏輯很簡(jiǎn)單
- 入?yún)閚ull則返回true
- 入?yún)⒉粸镾tring類型返回false
- 入?yún)?duì)象和this對(duì)象都為String就比較它們內(nèi)置的char[]數(shù)組長(zhǎng)度和每個(gè)char元素是否相同,滿足則返回true,否則返回false
而我的問(wèn)題就是由第二點(diǎn)引起的,因?yàn)轭愋筒幌嗤丞ぉ卅啜t(‵□′╰)
教訓(xùn)總結(jié)
- 不建議使用Spring的StringUtils的isEmpty()對(duì)非String類型的對(duì)象判空。(這里建議換成apache common的StringUtils或者Google Guava的Strings,這兩個(gè)工具包都是類型強(qiáng)約束的)
- 無(wú)論是修改哪處的代碼都最好檢查一下引用,避免修復(fù)小問(wèn)題引出大問(wèn)題
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Spring Boot基礎(chǔ)入門之基于注解的Mybatis
這篇文章主要給大家介紹了關(guān)于Spring Boot基礎(chǔ)入門之基于注解的Mybatis的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2018-07-07
java數(shù)據(jù)結(jié)構(gòu)基礎(chǔ):緒論
這篇文章主要介紹了Java的數(shù)據(jù)解構(gòu)基礎(chǔ),希望對(duì)廣大的程序愛(ài)好者有所幫助,同時(shí)祝大家有一個(gè)好成績(jī),需要的朋友可以參考下,希望能給你帶來(lái)幫助2021-07-07
SpringBoot中MyBatis-Flex的集成和使用實(shí)現(xiàn)
MyBatis-Flex是一個(gè)基于MyBatis的數(shù)據(jù)訪問(wèn)框架,MyBatis-Flex能夠極大地提高我們的開(kāi)發(fā)效率和開(kāi)發(fā)體驗(yàn),本文主要介紹了SpringBoot中MyBatis-Flex的集成和使用實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下2023-12-12
drools的簡(jiǎn)單入門案例場(chǎng)景分析
drools是一款由JBoss組織提供的基于Java語(yǔ)言開(kāi)發(fā)的開(kāi)源規(guī)則引擎,可以將復(fù)雜且多變的業(yè)務(wù)規(guī)則從硬編碼中解放出來(lái),這篇文章主要介紹了drools的簡(jiǎn)單入門案例,需要的朋友可以參考下2022-05-05
一文學(xué)會(huì)使用sa-token解決網(wǎng)站權(quán)限驗(yàn)證
這篇文章主要為大家介紹了使用sa-token解決網(wǎng)站權(quán)限驗(yàn)證方法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-07-07
SpringBoot實(shí)現(xiàn)動(dòng)態(tài)增刪啟停定時(shí)任務(wù)的方式
在spring?boot中,可以通過(guò)@EnableScheduling注解和@Scheduled注解實(shí)現(xiàn)定時(shí)任務(wù),也可以通過(guò)SchedulingConfigurer接口來(lái)實(shí)現(xiàn)定時(shí)任務(wù),但是這兩種方式不能動(dòng)態(tài)添加、刪除、啟動(dòng)、停止任務(wù),本文給大家介紹SpringBoot實(shí)現(xiàn)動(dòng)態(tài)增刪啟停定時(shí)任務(wù)的方式,感興趣的朋友一起看看吧2024-03-03
MyBatis-plus報(bào)錯(cuò)Property ‘sqlSessionFactory‘ or 
這篇文章主要給大家介紹了MyBatis-plus 報(bào)錯(cuò) Property ‘sqlSessionFactory‘ or ‘sqlSessionTemplate‘ are required的兩種解決方法,如果遇到相同問(wèn)題的朋友可以參考借鑒一下2023-12-12
使用Java將字節(jié)數(shù)組轉(zhuǎn)成16進(jìn)制形式的代碼實(shí)現(xiàn)
在很多場(chǎng)景下,需要進(jìn)行分析字節(jié)數(shù)據(jù),但是我們存起來(lái)的字節(jié)數(shù)據(jù)一般都是二進(jìn)制的,這時(shí)候就需要我們將其轉(zhuǎn)成16進(jìn)制的方式方便分析,本文主要介紹如何使用Java將字節(jié)數(shù)組格式化成16進(jìn)制的格式并輸出,需要的朋友可以參考下2024-05-05

