这是一个非常经典且容易让人困惑的问题,因为 split() 方法的行为会依赖于你使用的 Java 版本。

- 在 Java 8 及更高版本中:
"".split(",")会返回一个长度为 1 的数组[""]。 - 在 Java 7 及更低版本中:
"".split(",")会返回一个长度为 0 的数组[]。
下面我们深入探讨原因、不同情况以及最佳实践。
Java 8 及更高版本(推荐行为)
从 Java 8 开始,split() 方法的实现被修改,使其行为更加一致和可预测。
代码示例
import java.util.Arrays;
public class SplitEmptyStringJava8 {
public static void main(String[] args) {
String emptyString = "";
// 使用逗号作为分隔符
String[] parts1 = emptyString.split(",");
System.out.println("Splitting empty string with ',': " + Arrays.toString(parts1));
System.out.println("Array length: " + parts1.length);
System.out.println("--------------------");
// 使用正则表达式(匹配任意字符)
String[] parts2 = emptyString.split(".");
System.out.println("Splitting empty string with '.': " + Arrays.toString(parts2));
System.out.println("Array length: " + parts2.length);
}
}
输出结果
Splitting empty string with ',': []
Array length: 0
--------------------
Splitting empty string with '.': []
Array length: 0
解释:
在 Java 8 中,对于空字符串,无论你使用什么分隔符(甚至是正则表达式),split() 方法都会返回一个长度为 0 的空数组 [],这非常直观:一个没有任何内容的字符串,被分割后,自然也不应该有任何部分。
Java 7 及更低版本(旧版行为)
在 Java 7 及更早的版本中,split() 的行为有所不同,并且其行为与传入的 limit 参数有关。

limit 参数的作用
split(String regex, int limit) 方法的第二个参数 limit 用来控制分割的次数。
limit > 0:最多分割limit - 1次,数组长度最多为limit。limit < 0:分割次数没有限制。limit == 0:这是最关键的情况,它会去掉结果末尾的空字符串。
代码示例
import java.util.Arrays;
public class SplitEmptyStringJava7 {
public static void main(String[] args) {
String emptyString = "";
// 情况1: 不使用 limit (等同于 limit=0)
// 在 Java 7 中,这会去掉结果末尾的空字符串。
// 由于分割后只有一个 "",它被视为末尾的空字符串,因此被移除了。
String[] parts1 = emptyString.split(",");
System.out.println("Splitting without limit (limit=0): " + Arrays.toString(parts1));
System.out.println("Array length: " + parts1.length);
System.out.println("--------------------");
// 情况2: 使用 limit > 0
// 限制分割次数为 1,所以结果数组最多包含 1 个元素。
// 空字符串被分割后,会包含一个 "" 元素。
String[] parts2 = emptyString.split(",", 1);
System.out.println("Splitting with limit=1: " + Arrays.toString(parts2));
System.out.println("Array length: " + parts2.length);
}
}
输出结果 (Java 7 环境)
Splitting without limit (limit=0): []
Array length: 0
--------------------
Splitting with limit=1: [""]
Array length: 1
解释:
split(","):在 Java 7 中,这等同于split(",", 0),因为limit=0,它会移除结果末尾的空字符串,分割空字符串得到[""],移除后就是[]。split(",", 1):limit=1表示最多分割一次,结果数组最多包含一个元素,空字符串被分割后,自然就是[""],这个结果不会被移除。
为什么会有这种差异?
这种差异源于 Java 对 split() 方法实现的一次改进,在 Java 8 之前,split() 的底层实现有时会先产生一个包含空字符串的中间结果,然后再根据 limit 参数(特别是 limit=0)来清理这个结果,Java 8 的实现更加直接,它正确地处理了空字符串的边界情况,使其行为更符合逻辑。
其他边界情况
除了完全的空字符串 ,还有一些相关的情况值得注意:

1 只包含分隔符的字符串
字符串 。
String s = ",,,";
String[] parts = s.split(",");
// 在所有 Java 版本中,结果都是: ["", "", "", ""]
// 长度为 4
这很直观:在三个逗号之间,有三个空的部分,再加上开头和结尾,总共是四个空字符串。
2 空白字符串 (一个空格)
String s = " ";
String[] parts = s.split(" ");
// 在所有 Java 版本中,结果都是: ["", ""]
// 长度为 2
解释:一个空格把字符串分成了两部分:空格前面是空字符串,空格后面也是空字符串。
最佳实践与建议
由于 Java 版本差异可能导致行为不一致,如果你需要编写跨版本的兼容代码,或者想明确表达你的意图,可以考虑以下方法:
1 明确检查空字符串
这是最安全、最清晰的方法,在调用 split() 之前,先判断字符串是否为空。
String input = ""; // 或者从其他地方获取
if (input == null || input.isEmpty()) {
// 处理空字符串的情况,例如返回一个空数组
String[] result = new String[0];
// 或者返回一个包含单个空字符串的数组,取决于你的业务逻辑
// String[] result = new String[]{""};
System.out.println("Input is empty, result: " + Arrays.toString(result));
} else {
String[] result = input.split(",");
System.out.println("Split result: " + Arrays.toString(result));
}
2 使用 limit 参数
如果你希望总是得到一个至少包含一个元素的数组(即使输入是空字符串),可以显式地传入 limit=1。
String emptyString = "";
String[] parts = emptyString.split(",", 1); // 在所有版本中都会返回 [""]
System.out.println(Arrays.toString(parts)); // 输出: [""]
3 明确你的 Java 版本
如果你的项目可以锁定在 Java 8 或更高版本,那么可以直接使用 split(),它的行为是现代且一致的。
| 情况 | Java 8+ 行为 | Java 7- 行为 (无 limit) | Java 7- 行为 (limit=1) |
|---|---|---|---|
"".split(",") |
[] (长度 0) |
[] (长度 0) |
[""] (长度 1) |
"".split(".") |
[] (长度 0) |
[] (长度 0) |
[""] (长度 1) |
最终建议:
为了代码的健壮性和可读性,最佳实践是在调用 split() 之前显式检查字符串是否为空,这样可以避免任何版本差异带来的意外,并且让代码的意图更加清晰。
