我试图检查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
覆盖的所有场景 .
-
是否有一个字符串会使
isEmpty
和isBlank
在测试用例中表现不同? -
假设没有,是否有其他考虑因为我应该选择
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 回答
我会选择
isBlank()
而不是isEmpty()
,因为trim()
会创建一个新的String对象,以后必须进行垃圾回收 . 另一方面,isBlank()
不会创建任何对象 .您可以查看包含Annotatinos
@NotEmpty
和@NotNull
的JSR 303 Bean Validtion . Bean验证很酷,因为您可以从方法的原始意图中分离验证问题 .请注意Character.isWhitespace可以识别Unicode字符并返回
true
表示Unicode空白字符 .另一方面,
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的语法 .这取决于 . 但是,我认为上述部分的解释应该足以让您做出决定 . 总结差异:
如果字符串仅包含U 0020下方的控制字符1和空格字符(U 0020),
isEmpty()
将认为该字符串为空isBlank
会认为该字符串为空如果它只包含Character.isWhitespace
方法定义的空白字符,其中包含Unicode空白字符 .1
U+007F DELETE
上还有一个控制字符,它不会被trim()
方法修剪 .两个 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它(删除尾随空格 - 在这种情况下就像删除所有空格) .为什么不能简单地使用嵌套的三元运算符来实现这一点 . 请查看示例代码
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)); }
输出如下
这里的前两个场景返回false(即null和empty),第三个场景返回true
这个简单的代码就足够了:
单元测试:
使用Java 8,您还可以使用可选功能进行过滤 . 要检查字符串是否为空,代码是纯Java SE而没有其他库 . 以下代码说明了一个isBlank()实现 .
String.trim()行为
StringUtils.isBlank()行为