String 增强:strip / isBlank / lines / repeat#
版本信息
- 方法:
strip/stripLeading/stripTrailing/isBlank/lines/repeat - 最低 JDK:11(随 JDK 11 标准库增强,无独立 JEP)
- API 文档:Java 11
java.lang.String
为什么需要#
JDK 8 的 String 做日常小活儿很别扭:去首尾空白只有 trim()(不认 Unicode 空白,连全角空格都删不掉);判空只能 isEmpty()(空白串不算空);按行切要 s.split("\n")(生成数组、还有尾部空串的坑);重复字符串要写循环或 Collections.nCopies。JDK 11 给 String 补了六个贴身方法,这些写法从此可以一行解决,且全程 Unicode 感知。
语法#
examples/string-api/ 里真实可运行的源码(snippets 嵌入,与示例零漂移):
package com.javamodern.stringapi;
import java.util.List;
import java.util.stream.Collectors;
// JDK 11 给 String 补了一批日常方法:strip / stripLeading / stripTrailing / isBlank / lines / repeat。
// 它们都是「Unicode 感知」的,区别于老的 trim()(只删 ASCII 控制符)。
public class StringApiDemo {
/** strip:去除首尾空白(Unicode 感知),比 trim 更彻底。 */
public static String strip(String s) {
return s.strip(); // (1)
}
/** 对照:trim 只删码点 <= U+0020 的字符,删不掉全角空格 U+3000。 */
public static boolean trimMissesFullWidthSpace() {
String s = " "; // 全角空格
return s.trim().isEmpty(); // false:trim 不认全角空格
}
/** strip 按 Unicode 判定空白,全角空格也能去掉。 */
public static boolean stripHandlesFullWidthSpace() {
String s = " ";
return s.strip().isEmpty(); // true
}
/** isBlank:空串或仅含空白(Unicode 感知)时为 true。 */
public static boolean isBlank(String s) {
return s.isBlank();
}
/** lines:按行终止符切分为 Stream<String>。 */
public static List<String> lines(String s) {
return s.lines().collect(Collectors.toList());
}
/** repeat:重复拼接 n 份。 */
public static String repeat(String s, int n) {
return s.repeat(n);
}
public static void main(String[] args) {
System.out.println("strip(' Java ') = [" + strip(" Java ") + "]");
System.out.println("trim 全角空格 isEmpty = " + trimMissesFullWidthSpace());
System.out.println("strip 全角空格 isEmpty = " + stripHandlesFullWidthSpace());
System.out.println("isBlank(' ') = " + isBlank(" "));
System.out.println("lines('a\\nb\\nc') = " + lines("a\nb\nc"));
System.out.println("repeat('ab', 3) = " + repeat("ab", 3));
}
}
- :material-lightbulb: 六个新方法:
strip/stripLeading/stripTrailing/isBlank/lines/repeat。注意strip是 Unicode 感知的——全角空格(U+3000)它能去掉,trim()去不掉。
运行 StringApiDemo.main 的实测输出(JDK 11):
strip(' Java ') = [Java]
trim 全角空格 isEmpty = false
strip 全角空格 isEmpty = true
isBlank(' ') = true
lines('a\nb\nc') = [a, b, c]
repeat('ab', 3) = ababab
与 JDK 8 旧写法对比#
String s = " Java ";
String t = s.trim(); // 不认全角空格等 Unicode 空白
boolean blank = s.length() == 0; // 空白串不算空,要自己写判断
String[] rows = s.split("\n"); // 数组,尾部空串易踩坑
String repeated = "";
for (int i = 0; i < 3; i++) repeated += "ab"; // 手写循环
String t = " Java ".strip(); // Unicode 感知去首尾空白
boolean blank = " ".isBlank(); // 空白串也算 blank
List<String> rows = "a\nb".lines().toList(); // 返回 Stream(.toList 是 16+)
String repeated = "ab".repeat(3); // 一行
底层原理#
这些方法本质都是对底层 byte[]/字符的封装,无新类型、无运行时开销。关键差异在空白判定的标准:
trim()只删码点<= U+0020的字符(ASCII 控制符与空格)。strip()用Character.isWhitespace(),覆盖更广的 Unicode 空白(含全角空格 U+3000 等);但仍不删不间断空格 U+00A0(Java 的isWhitespace显式排除 NBSP,要删它得用Character.isSpaceChar())。lines()按规范行终止符(\n/\r/\r\n)惰性切分成Stream<String>,且结尾换行不产生尾部空串(与split的语义差异)。
graph LR
S["String(JDK 11 新方法)"] --> A["strip:Unicode 空白"]
S --> B["isBlank:空白即空"]
S --> C["lines:Stream 行流"]
S --> D["repeat:拼接 N 份"]
T["trim(JDK 8 老方法)"] -.只认 ASCII 空白.- A
style S fill:#bbdefb
style T fill:#ffcdd2
常见坑 / 最佳实践#
trim()还在,但优先用strip():除非要刻意保留 ASCII-only 行为,新代码一律strip。isBlank()≠isEmpty():isBlank()对空白串返回true,isEmpty()只认零长度。判"用户没填"用isBlank()。lines()末尾不补空串:"a\n".lines()得到[a],而"a\n".split("\n")得到[a, ""]——替换时注意。repeat(0)返回空串、repeat(n<0)抛IllegalArgumentException。
小结#
JDK 11 的 String 六件套是纯收益的小台阶——零运行时成本,却把 trim/循环/split 的啰嗦与坑一次性消掉,日常代码里几乎天天都用。