在 Java 中,对 String 类型进行“空”判断是一个非常常见且重要的操作,这里的“空”通常包含两种情况:
null:表示这个字符串变量没有指向任何对象。- (空字符串):表示这是一个存在的字符串对象,但其内部没有任何字符。
直接对 null 调用任何方法(如 .length() 或 .isEmpty())都会抛出 NullPointerException,必须使用安全的方式进行判断。
下面我将从传统方式到现代方式,为你详细梳理 Java 中字符串空判断的最佳实践。
传统方式 (Java 7 及之前)
在早期 Java 版本中,最安全、最标准的判断方式是使用 equals() 方法,因为它可以安全地处理 null 值。
a) 判断是否为 null 或空字符串 ()
这是最常见的场景,即“字符串是否为空或未定义”。
String str = null;
// 安全判断:先判断是否为 null,再判断是否为空字符串
if (str == null || str.equals("")) {
System.out.println("字符串为 null 或空字符串");
}
// 更简洁的写法:使用 String 的 isEmpty() 方法
if (str == null || str.isEmpty()) {
System.out.println("字符串为 null 或空字符串");
}
为什么 str == null 必须放在前面?
因为 Java 的逻辑或 () 具有短路特性,如果第一个条件 str == null 为 true,整个表达式的结果就已经确定为 true,Java 不会再去执行第二个条件 str.isEmpty(),从而避免了因 str 为 null 而调用方法导致的 NullPointerException。
b) 判断是否为 null 或空白字符串 (包含空格、制表符、换行等)
一个字符串只包含空格,我们也认为它是“空的”。
String str = " \t\n"; // 包含空格和制表符
// 传统方法:手动去除空白字符后判断
if (str == null || str.trim().isEmpty()) {
System.out.println("字符串为 null 或仅包含空白字符");
}
trim() 方法会去掉字符串首尾的空白字符,然后我们再判断处理后的字符串是否为空。
现代方式 (Java 8 及之后)
Java 8 引入了 java.util.Objects 工具类,它提供了一系列非常方便的静态方法来处理对象,Objects.isEmpty() 是一个革命性的改进。
a) java.util.Objects.isEmpty() (推荐)
这是目前最推荐、最简洁、最安全的方式。
import java.util.Objects;
String str1 = null;
String str2 = "";
String str3 = "Hello";
String str4 = " ";
// 判断是否为 null 或空字符串 ("")
System.out.println(Objects.isEmpty(str1)); // true
System.out.println(Objects.isEmpty(str2)); // true
System.out.println(Objects.isEmpty(str3)); // false
System.out.println(Objects.isEmpty(str4)); // false (因为它不是空的,只是有空白字符)
// 内部实现原理类似于: (str == null || str.length() == 0)
// 它比 .isEmpty() 更高效,因为 .length() 是一个原生方法,通常比调用 .isEmpty() 方法更快。
b) java.util.Objects.requireNonNull()
这个方法不是用来判断,而是用来校验,如果传入的参数为 null,它会立即抛出 NullPointerException,常用于方法参数的校验。
import java.util.Objects;
public void processName(String name) {
// name 为 null,立即抛出 NullPointerException,并给出清晰的错误信息
Objects.requireNonNull(name, "名称不能为 null");
// ... 其他业务逻辑
}
// 调用
processName(null); // 抛出: java.lang.NullPointerException: 名称不能为 null
第三方库方式
在大型项目中,使用 Apache Commons Lang 或 Google Guava 等库是常见的做法,它们提供了更丰富的字符串工具。
a) Apache Commons Lang - StringUtils
需要添加依赖:
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.12.0</version>
</dependency>
import org.apache.commons.lang3.StringUtils; String str1 = null; String str2 = ""; String str3 = "Hello"; String str4 = " "; // 判断是否为 null 或空字符串 System.out.println(StringUtils.isEmpty(str1)); // true System.out.println(StringUtils.isEmpty(str2)); // true System.out.println(StringUtils.isEmpty(str3)); // false System.out.println(StringUtils.isEmpty(str4)); // false // 判断是否为 null、空字符串或仅包含空白字符 (功能与 trim().isEmpty() 类似) System.out.println(StringUtils.isBlank(str1)); // true System.out.println(StringUtils.isBlank(str2)); // true System.out.println(StringUtils.isBlank(str3)); // false System.out.println(StringUtils.isBlank(str4)); // true <-- 这是它与 isEmpty() 的关键区别
StringUtils.isBlank() 是一个非常实用的方法,它完美地解决了判断“空白字符串”的需求。
b) Google Guava - Strings
需要添加依赖:
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>31.1-jre</version>
</dependency>
import com.google.common.base.Strings; String str1 = null; String str2 = ""; String str3 = "Hello"; String str4 = " "; // 判断是否为 null 或空字符串 System.out.println(Strings.isNullOrEmpty(str1)); // true System.out.println(Strings.isNullOrEmpty(str2)); // true System.out.println(Strings.isNullOrEmpty(str3)); // false System.out.println(Strings.isNullOrEmpty(str4)); // false // Guava 没有直接叫 isBlank 的方法,但可以组合使用 System.out.println(Strings.isNullOrEmpty(str4) || str4.trim().isEmpty()); // true
总结与最佳实践
| 场景 | 推荐方法 | 说明 |
|---|---|---|
判断是否为 null 或 |
Objects.isEmpty(str) (Java 8+) |
最推荐,简洁、高效、安全,是 Java 官方提供的最佳实践。 |
str == null || str.isEmpty() (Java 7-) |
经典、安全,在不能使用 Java 8 的环境下是标准做法。 | |
判断是否为 null、 或纯空白 |
StringUtils.isBlank(str) (Apache Commons) |
非常推荐,功能强大,代码可读性高,广泛用于企业级项目。 |
str == null || str.trim().isEmpty() (Java 7-) |
原生 Java 实现,无需额外依赖,但稍显冗长。 | |
方法参数校验,防止 null |
Objects.requireNonNull(str, "错误信息") (Java 8+) |
最佳实践,在方法入口处明确校验,使契约更清晰。 |
判断是否为 null 或 |
StringUtils.isEmpty(str) (Apache Commons) |
如果项目已引入 Commons Lang,这也是一个非常好的选择。 |
代码示例:综合应用
import java.util.Objects;
import org.apache.commons.lang3.StringUtils;
public class StringValidationExample {
public static void main(String[] args) {
String input = " ";
// 场景1:如果只是想判断是否为空或未定义
if (Objects.isEmpty(input)) {
System.out.println("输入为空或未定义。");
} else {
System.out.println("输入有内容: " + input);
}
// 场景2:如果需要判断是否为空白(包括空格)
if (StringUtils.isBlank(input)) {
System.out.println("输入为空、未定义或仅包含空白字符。");
} else {
System.out.println("输入有实际内容: " + input);
}
// 场景3:在方法中进行参数校验
processData(input);
}
public static void processData(String data) {
// 明确要求 data 不能为 null
Objects.requireNonNull(data, "处理数据时,数据不能为 null");
// 如果业务逻辑上不允许空白字符串
if (StringUtils.isBlank(data)) {
// 可以选择抛出异常或返回
throw new IllegalArgumentException("处理数据时,数据不能为空白字符串");
}
System.out.println("数据处理成功: " + data);
}
}
核心建议:
- 优先使用
java.util.Objects:如果你的项目使用的是 Java 8 或更高版本,Objects.isEmpty()和Objects.requireNonNull()应该是你的首选,因为它们是标准库的一部分,无需额外依赖。 - 考虑
StringUtils.isBlank():如果你的项目已经依赖了 Apache Commons Lang,或者你的业务逻辑中频繁需要判断“空白字符串”,StringUtils.isBlank()是一个极佳的选择,能极大提升代码的可读性和简洁性。
