
StringTokenizer 还能用吗?
能用,但不推荐新项目使用——它被标记为 Legacy,Java 官方文档明确说“建议用 String.split() 或 java.util.Scanner 替代”。它不支持正则、不能跳过空 token、不可重用,且 API 设计僵硬。除非维护老代码或嵌入式环境(如某些 Java ME 场景),否则别主动选它。
StringTokenizer 构造时分隔符传错会怎样?
传入空字符串 "" 会直接抛 NullPointerException;传入 null 同样崩。更常见的是误把正则当普通字符:比如想按点号 . 切分 "a.b.c",却写成 new StringTokenizer("a.b.c", ".")——这其实没问题,因为 StringTokenizer 不走正则,. 就是字面量。但如果你习惯 split("\."),这里反而容易多加转义,白折腾。
注意这些细节:
-
StringTokenizer的分隔符是「字符集合」,不是「分隔字符串」:传" ,;"表示空格、逗号、分号任一都切,不是匹配整个子串 - 默认分隔符是
" "(空格、tab、换行等),且自动忽略首尾空白,中间连续分隔符只算一个 - 第三个布尔参数
returnDelims设为true时,分隔符本身也会作为 token 返回,但顺序和原始位置不易推断,慎用
nextToken() 调用前不检查 hasMoreTokens() 会崩溃
这是最常踩的坑:nextToken() 遇到末尾直接抛 NoSuchElementException,它不返回 null。不像 Iterator.next() 至少有文档提醒,StringTokenizer 的这个行为非常反直觉。
立即学习“Java免费学习笔记(深入)”;
安全写法只有这一种模式:
StringTokenizer st = new StringTokenizer("a,b,c", ",");
while (st.hasMoreTokens()) {
String token = st.nextToken(); // 此时 guaranteed 安全
System.out.println(token);
}
别写 if (st.hasMoreTokens()) st.nextToken() 然后接着调第二次——只要没再判,就可能崩。
为什么 split() 比 StringTokenizer 更可靠?
根本差异在语义:前者是「按分隔模式切分字符串」,后者是「按字符集逐个扫描跳过」。这导致几个实际问题:
- 处理 CSV 类数据时,
StringTokenizer无法区分"a,,b"中的空字段(它会返回"a"、"b",丢掉中间那个空 token);而"a,,b".split(",", -1)能保留全部三个 token -
split()支持正则,可处理复杂边界,比如"foo, bar; baz".split("[,;]\s*") -
StringTokenizer是 mutable 对象,不可重用;split()是无状态纯函数,线程安全 - 性能上,简单单字符分隔时
StringTokenizer略快,但现代 JVM 优化后差距微乎其微,不值得为这点吞吐牺牲可维护性
老代码里如果看到 StringTokenizer,别急着改——先确认它是否依赖了 returnDelims 或连续分隔符合并行为。这些隐含逻辑一旦挪到 split(),得靠额外 trim 和 filter 补齐。










