string.format 输出空字符串或报错主因是参数类型不匹配或数量不足,如%d格式化null或参数少于占位符,抛illegalformatconversionexception或missingformatargumentexception;需确保类型兼容(%d→int/long,%s→任意对象含null)、参数数≥占位符数。

String.format 为什么输出空字符串或报错
常见现象是传入参数类型不匹配,比如用 %d 格式化 null 的 String,或整数参数少于格式串中的占位符数量。这时会抛 IllegalFormatConversionException 或 MissingFormatArgumentException。
关键点在于:格式串和参数必须一一对应,且类型兼容。Java 不做隐式类型转换(比如 %d 不接受 Double)。
- 检查每个
%占位符的类型标识符是否与对应参数实际类型一致(%s→ 任意对象,%d→int/long,%f→float/double) - 避免对
null使用%d、%f等非字符串类型占位符;%s可安全处理null(输出"null"字符串) - 参数个数必须 ≥ 占位符个数;多出的参数会被忽略,但少一个就会直接抛异常
示例:String.format("ID:%d, name:%s", null, "Alice") → 报错;应改为 String.format("ID:%s, name:%s", null, "Alice") 或先判空。
System.out.printf 和 String.format 的行为差异
两者共享同一套格式语法(都基于 java.util.Formatter),但目标不同:printf 直接输出到控制台,String.format 返回新字符串。这意味着它们在副作用、线程安全和调试体验上表现不同。
立即学习“Java免费学习笔记(深入)”;
-
printf是带副作用的操作,无法被赋值或组合;String.format是纯函数式,适合拼接、缓存、日志预处理 - 多线程环境下,
System.out是共享的,连续多次printf可能被其他线程输出打断(出现乱序),而String.format没这个问题 -
printf不自动换行,容易漏写%n导致后续输出粘连;String.format完全由你控制结尾字符
示例:System.out.printf("count:%d%n", 42) 输出后换行;而 String.format("count:%d", 42) 就只是 "count:42",没换行符。
中文环境下的日期和数字格式乱码或显示异常
用 %tF、%,.2f 这类格式时,如果系统默认 Locale 是中文(如 zh_CN),千位分隔符可能是逗号也可能是万/亿单位,小数点可能变成顿号——但 Java 默认只按 Locale 控制分隔符,不自动转中文数字。
- 显式指定 Locale 更可靠:
String.format(Locale.US, "%.2f", 1234567.89)强制用英文格式 -
%,d在zh_CN下仍输出逗号分隔(如1,234,567),不是「123万」;真要中文大写数字需自行实现 - 日期格式如
%tY-%tm-%td不受 Locale 影响,但%tB(完整月份名)会输出中文“一月”,此时若终端编码不支持 UTF-8 就会显示为??
验证方式:打印 Locale.getDefault(),再确认终端或日志系统的字符集是否为 UTF-8。
性能敏感场景下该不该用 String.format
在高频日志、循环内拼接或响应时间要求严苛的代码中,String.format 因反射解析格式串、创建临时对象、内部 StringBuilder 扩容等,比字符串拼接或 MessageFormat 更重。
- 简单拼接(≤3 个变量)优先用
+(JDK 9+ 会优化为StringConcatFactory) - 固定格式 + 多次复用,考虑预编译:
new Formatter(new StringBuilder(), Locale.US).format("...")避免重复解析 - Log4j/SLF4J 等日志框架已对
{}占位做零分配优化,比String.format更轻量,别在日志里套一层String.format
一个典型陷阱:log.info("user {} login at {}", user.getId(), new Date()) 是高效写法;写成 log.info(String.format("user %d login at %tF", ...)) 就多了一次无谓的格式化。
真正麻烦的是嵌套格式(比如动态生成格式串)、跨 Locale 兼容、以及和旧版 Android(API Formatter 行为差异——这些地方容易漏测,上线后才暴露。










