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

接着往内:可以看到这个抽象类被这些类继承了

随便点一个进去看一下:

到这里以及后面都是非常底层的东西了,目前超出能力范围,学习之后会再做补充。

如果文章对你有帮助,不要忘了给我点个赞吼( ̄▽ ̄)~
欢迎关注我的微信公众号:松鼠技术站