最近在写CRUD
的时候,发现有个分页的VO
写的健壮性比较差,一时手痒改了一下,没想到改了以后好几个功能都出现了问题。前端
原VO
关键代码以下:apache
public class PageVo implements Serializable{ // ...省略全部无关代码 Map<String, String> query }
这个VO
是用于从前端分页查询时传参,而query
是用于传递查询条件的(这里不讨论用Map
传参是否合理)。当前端无查询条件时则会致使query
为null
,若是不注意容易出现NPE
。数组
因此我就改形成下面这样了。工具
public class PageVo implements Serializable{ // ...省略全部无关代码 Map<String, String> query=new HashMap<> }
可是没想到就是这么简单的改造竟然都翻车(・ε・`)源码分析
没办法,只好去排查问题。this
想过不少种缘由,可是我真没想到竟然是由于这样(/‵Д′)/~ ╧╧,很少说了,问题关键代码以下:设计
if (StringUtils.isEmpty(page.getQuery())) { // 省略处理逻辑 }
竟然用StringUtils
去判断一个Map
是否为空,好歹也换个CollectionUtils
啊(╬ ̄皿 ̄)凸code
虽然是前人挖坑,可是为何Spring
的`StringUtils
竟然设计成支持Object
入参呢o_o ....对象
想了一下,仍是去看看源码吧get
StringUtils
的isEmpty()
方法源码超级简单,三行代码搞定(其实严格来讲就一行代码):
public static boolean isEmpty(@Nullable Object str) { return (str == null || "".equals(str)); }
既然个人Map
对象不为null
,那么问题应该是由于String
的equals()
方法。很少说,继续跟踪源码
public boolean equals(Object anObject) { if (this == anObject) { return true; } // 问题出在这里 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; }
这个equals()
方法的逻辑很简单
null
则返回true
String
类型返回false
this
对象都为String
就比较它们内置的char[]
数组长度和每一个char
元素是否相同,知足则返回true
,不然返回false
而个人问题就是由第二点引发的,由于类型不相同┴─┴︵╰(‵□′╰)
Spring
的StringUtils
的isEmpty()
对非String
类型的对象判空。(这里建议换成apache common
的StringUtils
或者Google Guava
的Strings
,这两个工具包都是类型强约束的)