String.format()不截断超长字符串,仅通过%.Ns实现截断+填充;%-w.Ns可左对齐、截取前N字符并补空格至宽度w;需手动处理null及Unicode边界问题。

Java中用String.format()控制字符串长度:截断还是填充?
String.format()本身不直接支持截断,但能通过格式化语法实现左/右填充和固定宽度。关键在%s前加宽度修饰符:%5s表示至少占5字符,右对齐、左侧补空格;%-5s左对齐、右侧补空格。若原字符串超长(如"hello world"塞进%5s),它会原样输出,**不会截断**——这是最容易踩的坑。
常见误用场景:想把用户昵称统一显示为6位,用String.format("%6s", nick)结果发现超长昵称依然显示10个字。此时必须手动截断:
String.format("%6s", nick.substring(0, Math.min(nick.length(), 6)))
用java.text.MessageFormat做带截断的模板化填充
MessageFormat比String.format()更灵活,支持自定义格式子句,但默认也不含截断逻辑。需配合substring()或正则预处理。例如要保证每个字段最多4字符、不足则右补'0':
String padded = String.format("%-4.4s", nick); // %-4.4s:最小宽4,最大截取4 → 实现“截断+左对齐”
这里.4是精度(precision)修饰符,对字符串即最大长度,配合-可同时控制对齐与截断。注意:%.4s不指定最小宽度时,只截不断,也不填充。
立即学习“Java免费学习笔记(深入)”;
-
%10.5s:至少10宽,最多取前5字符 → 实际效果是左补空格到10位,内容只显示5字符(相当于先截后填) -
%-10.5s:左对齐,先截5字符,再右补空格到总长10 - 精度值大于字符串长度时,无截断效果,仅按原长参与对齐
Apache Commons Lang的StringUtils:一行解决截断+填充
如果项目已引入commons-lang3,StringUtils提供开箱即用的方法:leftPad()、rightPad()只负责填充;abbreviate()负责截断;三者组合才能闭环。最简方案是StringUtils.leftPad(StringUtils.abbreviate(str, maxWidth), maxWidth, padChar),但要注意abbreviate()会在末尾加"...",不适合纯截断场景。
推荐直接用StringUtils.substring(str, 0, maxWidth) + StringUtils.rightPad():
String result = StringUtils.rightPad(StringUtils.substring(nick, 0, 6), 6, "0");
这比手写Math.min()更安全(substring对负索引或越界自动处理),且rightPad明确区分填充字符与长度,不易混淆空格/零宽问题。
自定义工具方法:兼顾null安全、Unicode与性能
标准库和Commons都对null敏感(String.format()抛NullPointerException,StringUtils返回null或空串)。生产环境建议封装一层:
public static String truncateAndPad(String s, int width, char pad) {
if (s == null) s = "";
String truncated = s.substring(0, Math.min(s.length(), width));
return String.format("%" + width + "s", truncated).replace(' ', pad);
}
注意两点:一是String.format()中动态拼接格式串虽可行,但width为负会出错,需校验;二是用replace(' ', pad)替换空格填充,对中文等宽字符有效,但对emoji或组合字符(如带变音符号的字母)可能因JVM版本差异导致视觉宽度不准——这种边界情况只能靠java.awt.font.FontMetrics或第三方库(如ICU4J)精确测量像素宽度,不在字符串层面解决。











