跳转至

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));
    }
}
  1. :material-lightbulb: 六个新方法:strip / stripLeading / stripTrailing / isBlank / lines / repeat。注意 stripUnicode 感知的——全角空格 (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() 对空白串返回 trueisEmpty() 只认零长度。判"用户没填"用 isBlank()
  • lines() 末尾不补空串"a\n".lines() 得到 [a],而 "a\n".split("\n") 得到 [a, ""]——替换时注意。
  • repeat(0) 返回空串、repeat(n<0)IllegalArgumentException

小结#

JDK 11 的 String 六件套是纯收益的小台阶——零运行时成本,却把 trim/循环/split 的啰嗦与坑一次性消掉,日常代码里几乎天天都用。

参考#