首页 文章

在Java中检查非空,而不是空白的字符串

提问于
浏览
62

我试图检查Java字符串是不是 null ,不是空的而不是空格 .

在我看来,这段代码应该完全适合这项工作 .

public static boolean isEmpty(String s) {
    if ((s != null) && (s.trim().length() > 0))
        return false;
    else
        return true;
}

根据文档,String.trim()应该如此工作:

返回字符串的副本,省略前导和尾随空格 . 如果此String对象表示空字符序列,或者此String对象表示的字符序列的第一个和最后一个字符的代码都大于'\ u0020'(空格字符),则返回对此String对象的引用 .

但是, apache/commons/lang/StringUtils.java 有点不同 .

public static boolean isBlank(String str) {
    int strLen;
    if (str == null || (strLen = str.length()) == 0) {
        return true;
    }
    for (int i = 0; i < strLen; i++) {
        if ((Character.isWhitespace(str.charAt(i)) == false)) {
            return false;
        }
    }
    return true;
}

根据文档,Character.isWhitespace()

根据Java确定指定的字符是否为空格 . 当且仅当它满足以下条件之一时,字符才是Java空白字符:它是Unicode空格字符(SPACE_SEPARATOR,LINE_SEPARATOR或PARAGRAPH_SEPARATOR),但也不是不间断的空格('\ u00A0','\ u2007','\ u202F') . 这是'\ t',U 0009 HORIZONTAL TABULATION . 这是'\ n',U 000A LINE FEED . 这是'\ u000B',U 000B VERTICAL TABULATION . 这是'\ f',U 000C FORM FEED . 这是'\ r',U 000D CARRIAGE RETURN . 它是'\ u001C',U 001C FILE SEPARATOR . 它是'\ u001D',U 001D GROUP SEPARATOR . 这是'\ u001E',U 001E RECORD SEPARATOR . 这是'\ u001F',U 001F UNIT SEPARATOR .

如果我没有弄错 - 或者可能是我只是没有正确阅读 - String.trim() 应该带走 Character.isWhiteSpace() 正在检查的任何字符 . 所有人都认为高于 '\u0020' .

在这种情况下,更简单的 isEmpty 函数似乎涵盖了更长的 isBlank 覆盖的所有场景 .

  • 是否有一个字符串会使 isEmptyisBlank 在测试用例中表现不同?

  • 假设没有,是否有其他考虑因为我应该选择 isBlank 而不使用 isEmpty

对于那些对实际运行测试感兴趣的人,这里有方法和单元测试 .

public class StringUtil {

    public static boolean isEmpty(String s) {
        if ((s != null) && (s.trim().length() > 0))
            return false;
        else
            return true;
    }

    public static boolean isBlank(String str) {
        int strLen;
        if (str == null || (strLen = str.length()) == 0) {
            return true;
        }
        for (int i = 0; i < strLen; i++) {
            if ((Character.isWhitespace(str.charAt(i)) == false)) {
                return false;
            }
        }
        return true;
    }
}

和单元测试

@Test
public void test() {

    String s = null; 
    assertTrue(StringUtil.isEmpty(s)) ;
    assertTrue(StringUtil.isBlank(s)) ;

    s = ""; 
    assertTrue(StringUtil.isEmpty(s)) ;
    assertTrue(StringUtil.isBlank(s)); 

    s = " "; 
    assertTrue(StringUtil.isEmpty(s)) ;
    assertTrue(StringUtil.isBlank(s)) ;

    s = "   "; 
    assertTrue(StringUtil.isEmpty(s)) ;
    assertTrue(StringUtil.isBlank(s)) ;

    s = "   a     "; 
    assertTrue(StringUtil.isEmpty(s)==false) ;    
    assertTrue(StringUtil.isBlank(s)==false) ;       

}

更新:这是一个非常有趣的讨论 - 这就是为什么我喜欢Stack Overflow和这里的人们 . 顺便说一句,回到问题,我们得到:

  • 显示所有字符将使其行为不同的程序 . 代码位于https://ideone.com/ELY5Wv . 谢谢@Dukeling .

  • 选择标准 isBlank() 的性能相关原因 . 谢谢@devconsole .

  • @nhahtdh的综合解释 . 谢了哥们 .

8 回答

  • 0

    我会选择 isBlank() 而不是 isEmpty() ,因为 trim() 会创建一个新的String对象,以后必须进行垃圾回收 . 另一方面, isBlank() 不会创建任何对象 .

  • 0

    您可以查看包含Annotatinos @NotEmpty@NotNull 的JSR 303 Bean Validtion . Bean验证很酷,因为您可以从方法的原始意图中分离验证问题 .

  • 25

    是否有一个字符串会使isEmpty和isBlank在测试用例中表现不同?

    请注意Character.isWhitespace可以识别Unicode字符并返回 true 表示Unicode空白字符 .

    根据Java确定指定的字符是否为空格 . 当且仅当它满足以下条件之一时,字符才是Java空白字符:它是Unicode空格字符(SPACE_SEPARATOR,LINE_SEPARATOR或PARAGRAPH_SEPARATOR),但也不是不间断的空格('\ u00A0','\ u2007','\ u202F') . [...]

    另一方面, trim() 方法将修剪代码点低于U 0020的所有控制字符和空格字符(U 0020) .

    因此,在存在Unicode空白字符时,这两种方法的行为会有所不同 . 例如: "\u2008" . Or 当字符串包含 Character.isWhitespace 方法不考虑空格的控制字符时 . 例如: "\002" .

    如果你要编写一个正则表达式来执行此操作(这比通过字符串循环并检查更慢):

    • isEmpty() 相当于 .matches("[\\x00-\\x20]*")

    • isBlank() 相当于 .matches("\\p{javaWhitespace}*")

    isEmpty()isBlank() 方法都允许 null 字符串引用,因此它不完全等同于正则表达式解决方案,但将它放在一边,它是等效的) .

    请注意, \p{javaWhitespace} ,顾名思义,是用于访问 Character.isWhitespace 方法定义的字符类的特定于Java的语法 .

    假设没有,是否还有其他考虑,因为我应该选择isBlank而不使用isEmpty?

    这取决于 . 但是,我认为上述部分的解释应该足以让您做出决定 . 总结差异:

    如果字符串仅包含U 0020下方的控制字符1和空格字符(U 0020),

    • isEmpty() 将认为该字符串为空

    • isBlank 会认为该字符串为空如果它只包含 Character.isWhitespace 方法定义的空白字符,其中包含Unicode空白字符 .

    1 U+007F DELETE 上还有一个控制字符,它不会被 trim() 方法修剪 .

  • 4

    两个 standard 方法的目的是区分这两种情况:

    org.apache.common.lang.StringUtils.isBlank(" ") (将返回true) .

    org.apache.common.lang.StringUtils.isEmpty(" ") (将返回false) .

    您的 isEmpty() 的自定义实现将返回true .


    UPDATE:

    • org.apache.common.lang.StringUtils.isEmpty() 用于查找String的长度是0还是null .

    • org.apache.common.lang.StringUtils.isBlank() 向前迈进了一步 . 它不仅检查String是否为长度为0或null,还检查它是否只是一个空白字符串 .

    在您的情况下,您正在修剪 isEmpty 方法中的字符串 . 现在唯一可能发生的区别是不会发生(你给它 " " 的情况),因为你是trimming它(删除尾随空格 - 在这种情况下就像删除所有空格) .

  • 1

    为什么不能简单地使用嵌套的三元运算符来实现这一点 . 请查看示例代码 public static void main(String[] args) { String s = null; String s1=""; String s2="hello"; System.out.println(" 1 "+check(s)); System.out.println(" 2 "+check(s1)); System.out.println(" 3 "+check(s2)); } public static boolean check(String data) { return (data==null?false:(data.isEmpty()?false:true)); }

    输出如下

    1假2假3真

    这里的前两个场景返回false(即null和empty),第三个场景返回true

  • 0
    <% 
    System.out.println(request.getParameter("userName")+"*");
    
    if (request.getParameter("userName").trim().length() == 0 | request.getParameter("userName") == null) { %>
    <jsp:forward page="HandleIt.jsp" />
    <% }
     else { %>
    Hello ${param.userName}
    <%} %>
    
  • 32

    这个简单的代码就足够了:

    public static boolean isNullOrEmpty(String str) {
        return str == null || str.trim().equals("");
    }
    

    单元测试:

    @Test
    public void testIsNullOrEmpty() {
        assertEquals(true, AcdsUtils.isNullOrEmpty(""));
        assertEquals(true, AcdsUtils.isNullOrEmpty((String) null));
        assertEquals(false, AcdsUtils.isNullOrEmpty("lol    "));
        assertEquals(false, AcdsUtils.isNullOrEmpty("HallO"));
    }
    
  • 14

    使用Java 8,您还可以使用可选功能进行过滤 . 要检查字符串是否为空,代码是纯Java SE而没有其他库 . 以下代码说明了一个isBlank()实现 .

    String.trim()行为

    !Optional.ofNullable(tocheck).filter(e -> e != null && e.trim().length() > 0).isPresent()
    

    StringUtils.isBlank()行为

    Optional.ofNullable(toCheck)
        .filter(e -> 
            {
                int strLen;
                if (str == null || (strLen = str.length()) == 0) {
                    return true;
                }
                for (int i = 0; i < strLen; i++) {
                    if ((Character.isWhitespace(str.charAt(i)) == false)) {
                        return false;
                    }
                }
                return true;
    
            })
        .isPresent()
    

相关问题