详解Spring的StringUtils踩坑记录

作者:Null 时间:2021-08-23 16:14:39 

起因

最近在写CRUD的时候,发现有个分页的VO写的健壮性比较差,一时手痒改了一下,没想到改了之后好几个功能都出现了问题。

原VO关键代码如下:


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<>

}

但是没想到就是这么简单的改造居然都翻车(・ε・`)

没办法,只好去排查问题。

发现问题

想过很多种原因,但是我真没想到居然是因为这样(/‵Д′)/~ ╧╧,不多说了,问题关键代码如下:


if (StringUtils.isEmpty(page.getQuery())) {
 // 省略处理逻辑
}

居然用StringUtils去判断一个Map是否为空,好歹也换个CollectionUtils啊(╬ ̄皿 ̄)凸

虽然是前人挖坑,但是为什么Spring的`StringUtils居然设计成支持Object入参呢o_o ....

想了一下,还是去看看源码吧

源码分析

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()方法的逻辑很简单

  1. 入参为null则返回true

  2. 入参不为String类型返回false

  3. 入参对象和this对象都为String就比较它们内置的char[]数组长度和每个char元素是否相同,满足则返回true,否则返回false

而我的问题就是由第二点引起的,因为类型不相同┴─┴︵╰(‵□′╰)

教训总结

  1. 不建议使用Spring的StringUtils的isEmpty()对非String类型的对象判空。(这里建议换成apache common的StringUtils或者Google Guava的Strings,这两个工具包都是类型强约束的)

  2. 无论是修改哪处的代码都最好检查一下引用,避免修复小问题引出大问题

来源:https://segmentfault.com/a/1190000021540565

标签:Spring,StringUtils
0
投稿

猜你喜欢

  • C#调用CMD命令实例

    2021-06-17 10:08:12
  • Android三种GSM手机定位技术分析

    2023-04-10 10:09:22
  • spring boot security设置忽略地址不生效的解决

    2022-06-07 16:37:30
  • Android 中StringBuffer 和StringBuilder常用方法

    2023-10-29 08:39:26
  • 浅谈idea live template高级知识_进阶(给方法,类,js方法添加注释)

    2023-12-07 22:50:28
  • 利用adt-bundle轻松搭建Android开发环境与Hello world(Windows)

    2022-09-05 14:35:18
  • C#如何利用反射将枚举绑定到下拉框详解

    2022-09-12 01:48:09
  • Java下SpringBoot创建定时任务详解

    2023-10-03 01:25:23
  • C#获取本地IP的四种方式示例详解

    2023-04-16 00:52:50
  • springboot项目打成war包部署到tomcat遇到的一些问题

    2023-10-12 12:46:46
  • Android自定义组件获取本地图片和相机拍照图片

    2022-07-09 21:54:48
  • Java中RedisUtils工具类的使用

    2022-05-04 21:32:32
  • ShardingSphere jdbc实现分库分表核心概念详解

    2023-11-24 12:09:45
  • C#异步调用示例详解

    2023-09-12 13:02:04
  • java开发Dubbo注解Adaptive实现原理

    2022-02-06 11:40:31
  • java通过ip获取客户端Mac地址的小例子

    2021-12-22 06:37:07
  • Android10 启动Zygote源码解析

    2021-10-11 07:53:13
  • Dubbo Consumer引用服务示例代码详解

    2022-04-26 03:56:44
  • Java使用synchronized实现互斥锁功能示例

    2022-10-20 00:47:49
  • JavaWeb入门教程之分页查询功能的简单实现

    2021-11-11 21:52:23
  • asp之家 软件编程 m.aspxhome.com