string.indent() 对 null 输入直接抛出 nullpointerexception 而非返回 null;indent(-n) 是逐行移除最多 n 个前导空格,不校验是否足够;换行符兼容各平台但需预先标准化;大文本大缩进易引发 oom。

String.indent() 为什么返回 null 而不是报错
因为 indent() 对 null 输入不做防御性检查,直接抛出 NullPointerException —— 它只处理字符串内容,不处理引用本身。常见错误是把未判空的 String 变量直接传入,比如日志拼接或配置读取后立刻调用:configValue.indent(4),而 configValue 实际为 null。
实操建议:
立即学习“Java免费学习笔记(深入)”;
- 务必在调用前检查:
if (str != null) str.indent(n) - 别依赖 IDE 自动补全的“看起来安全”,
indent()不像Objects.toString()那样自带空值兜底 - 如果上游可能为空,优先用
Optional.ofNullable(str).map(s -> s.indent(n)).orElse("")
indent(0) 和 indent(-1) 的行为差异
indent(0) 等价于原字符串(不加也不删空格),但 indent(-1) 不是“反向缩进”,而是按行移除最多 1 个前导空格(注意:只对每行生效,且仅移除空格,不处理制表符)。容易误以为负数能“去缩进”,结果发现缩进没变、甚至部分行被截断。
实操建议:
立即学习“Java免费学习笔记(深入)”;
-
indent(-n)实际是「逐行 trim 前 n 个空格」,若某行只有 2 个空格却用indent(-4),那 2 个全被删,不会报错也不会补空 - 需要真正“去缩进到最小公共前缀”,得用
String.lines().map(String::stripLeading).collect(Collectors.joining("\n")),indent()不负责这个 - 负数参数慎用:它不校验是否“足够缩进”,
"a".indent(-100)结果仍是"a"
换行符兼容性:Windows / Linux / macOS 下表现一致吗
一致,但前提是你的字符串里换行符本身就是标准化的。indent() 按 \n 切分行(内部用 String.lines()),所以如果原始字符串含 \r\n(Windows 风格),它会被识别为单个换行符,缩进仍正确添加;但若手动拼接了混合换行符(如 "line1\r\nline2\nline3"),lines() 会把 \r\n 和 \n 都当作分隔符,导致行数变多、缩进应用次数变多。
实操建议:
立即学习“Java免费学习笔记(深入)”;
- 调用前统一换行符:用
str.replaceAll("\r\n", "\n").replaceAll("\r", "\n") - 避免从旧系统读取文本后直传
indent(),尤其注意 Properties 文件、INI 配置等可能带\r - 输出时若需 Windows 风格,缩进后再整体替换:
result.replace("\n", "\r\n")
性能陷阱:大文本 + 大缩进值会卡住吗
会,但卡点不在缩进逻辑本身,而在字符串重复拼接。例如 str.indent(1000),如果原字符串有 1 万行,就会生成 1 万个长度为 1000 的空格字符串(每个都是新对象),再逐行拼接——JVM 堆压力陡增,GC 频繁,甚至 OOM。
实操建议:
立即学习“Java免费学习笔记(深入)”;
- 缩进值别硬写超大常量,如
indent(5000);真需要宽缩进,先确认是否可改用制表符("\t".repeat(n/4)更省内存) - 超长文本(>10MB 或 >10 万行)慎用
indent(),改用流式处理:逐行读、逐行缩进、逐行写文件 - 注意
indent()返回的是全新字符串,原字符串不可变,别在循环里反复调用还保留旧引用
最易被忽略的一点:缩进是“每行开头加空格”,不是“整体左移”。如果你的字符串末尾有换行符(比如以 "\n" 结尾),indent() 会在最后一行(空行)也加缩进——这常导致 JSON 或 XML 格式化后多出一个缩进空行,解析器不报错但肉眼难察觉。










