1. 方法的使用
首先我们先看这两个方法的使用
要使用它需要导入jar包:maven项目直接导入依赖即可
地址:https://mvnrepository.com/artifact/org.apache.commons/commons-lang3
isEmpty()
方法的使用:
String str="";
if(StringUtils.isEmpty(str)){
System.out.println("这个字符串为空!");
}
isBlank()
方法的使用:
String str="";
if(StringUtils.isBlank(str)){
System.out.println("这个字符串为空!");
}
乍一看好像是一样的没区别,但我们可以看一下这两个方法的实现
2. 方法的实现
isEmpty()
方法:
可以看到当字符串为null或者字符串长度为0的时候,判断字符串为空值(返回true)
public static boolean isEmpty(String str) {
return str == null || str.length() == 0;
}
isBlank()
方法:
是在 isEmpty 的基础上进行了为空(字符串为空格、制表符、tab 的情况)的判断
也就是说如果这个字符串内容为空格、tab、制表符(例如\t \r \n
等),isBlank()这个方法都认为你这个字符串是空的。
Character.isWhitespace(str.charAt(i))
这个方法先忽略,只需要知道是对字符串的判段即可
public static boolean isBlank(String str) {
int strLen;
if (str != null && (strLen = str.length()) != 0) {
for(int i = 0; i < strLen; ++i) {
// 判断字符是否为空格、制表符、tab
if (!Character.isWhitespace(str.charAt(i))) {
return false;
}
}
return true;
} else {
return true;
}
}
3. 实验测试
我们来做一个简单的测试:
public class Test {
public static void main(String[] args) {
String str01="";//字符串为空
String str02=" ";//字符串为空格
String str03=" ";//字符串为一个tab
String str04="\t";//字符串为制表符
List<String> list=new ArrayList<>();
list.add(str01);
list.add(str02);
list.add(str03);
list.add(str04);
Integer index=0;
for(String str : list){
if(StringUtils.isEmpty(str)){
System.out.println("isEmpty: "+index+"号这个字符串为空!");
}else{
System.out.println("isEmpty: "+index+"号这个字符串长度为:"+str.length());
}
if(StringUtils.isBlank(str)){
System.out.println("isBlank: "+index+"号这个字符串为空!");
}
index++;
}
}
}
测试结果如下:
可以看到,当字符串为空格、tab、制表符时,isBlank方法依旧会判断字符串为null
这个方法可以很好的为我们解决判空的繁琐问题,如果用 if else 来判空的话,光判空代码就会比较多,维护起来比较麻烦,而且自己写难免会出现考虑不全的问题,因此我们可以利用现成的工具类,帮助我们开发,感兴趣可以再深究。
强烈推荐使用第三方 jar 工具类去做判空:
从 Map 中取一个 key 的值,可以用 MapUtils 这个类;对字符串判空使用 StringUtils 这个类;对集合进行判空使用CollectionUtils 等等。这些类都可以通过引入 apache 的 commons 包系列使用。
了解到这里,其实就能够很好的使用了,但是耐不住我的好奇心,想要瞄一下源码,感兴趣的读者可以接着往下看。
4. 源码探究
源码如下
isEmpty()
方法:
public static boolean isEmpty(final CharSequence cs) {
return cs == null || cs.length() == 0;
}
isBlank()
方法:
public static boolean isBlank(final CharSequence cs) {
final int strLen = length(cs);
if (strLen == 0) {
return true;
}
for (int i = 0; i < strLen; i++) {
if (!Character.isWhitespace(cs.charAt(i))) {
return false;
}
}
return true;
}
与第2点的实现方法对比稍微有些区别,首先是方法的接收参数 String str在源码中是final CharSequence cs
它可以接收String类型的参数,这是为啥呢?不慌,稳住我们慢慢看:
英语不好不用怕,先翻译一下:哦,原来它是字符序列
字符序列是啥东西,我们先放一放,接着往后,点进去看一下
这就涉及到了JDK的源码了,这个类是一个接口,里面有一些方法:
我们再回到判空源码,点进String的实现类:可以看到它实现了这个接口
也就是说String类型其实是CharSequence类型
所以在前面我们提到的isEmpty等方法接收参数用CharSequence和String是一样的效果,StringBuilder、CharArray等都实现了该接口。
CharSequence接口的概述:
java.lang.CharSequence接口是一个可读的字符序列。此接口为不同类型的字符序列提供了一种统一且只读的访问方式。如String、StringBuilder、CharArray等都实现了该接口。
CharSequence接口没refine Object类中定义的equals和hashCode方法的通用约定,因此对于两个实现了该接口的对象而言,在进行对比时,通常其结果也是未定义的。同时,使用任意的CharSequence实例作为set集合的元素或者map中的key是不合适的,因为实现该接口的每个对象可以由不同的类来实现,导致无法保证每个类都有和其他类实例有等价的测试能力。
关于CharSequence接口方法解读,可以看一下这篇文章:
https://juejin.im/post/6844903760402055175
下面我们再稍微探究一下这个方法Character.isWhitespace(cs.charAt(i))
可以看到用的是Character的类
内部方法解析可以参考这篇文章:
https://blog.csdn.net/qq_25343557/article/details/101015418
isWhitespace
点进这个方法,可以看到用到了这个抽象类CharacterData(字符数据):
这个方法是做什么的呢?我们可以打开:JDK8的API官方文档找到这个方法的描述:
翻译过来的意思就是:根据Java,确定指定字符(Unicode代码点)是否为空白。当且仅当满足以下条件之一时,字符才是Java空白字符
也就是说,满足条件的就判定是空字符,要注意一下第一条条件的含义:
它是Unicode空格字符(空格分隔符、行分隔符或段落分隔符),但不是非分隔空格(’\u00A0’、’\u2007’、’\u202F’)。
啥意思呢?
我认为就是当str=" ";
会判断为null字符,但是你要是输入空格符str="\u00A0";
它就不会认为你是空的,具体可以自己按照前面的例子进行测试
Unicode相关可以看一下这个:
https://blog.csdn.net/u011389474/article/details/52931964
接着往内:可以看到这个抽象类被这些类继承了
随便点一个进去看一下:
到这里以及后面都是非常底层的东西了,目前超出能力范围,学习之后会再做补充。
如果文章对你有帮助,不要忘了给我点个赞吼( ̄▽ ̄)~
欢迎关注我的微信公众号:松鼠技术站