要保留完整百分号需用%%转义,千分位须紧贴类型符并显式指定locale.us,浮点百分比需先乘100,性能敏感场景应避免循环中调用string.format()。

百分号显示总被吃掉一个,怎么保留完整的 % 符号
String.format() 里 % 是转义起始符,直接写 "%d%" 会报 UnknownFormatConversionException —— 因为它把第二个 % 当成了格式说明的一部分,但后面没跟合法转换符。
正确做法是用两个连续的 %% 表示字面量的单个 %:
String s = String.format("完成度:%d%%", 95); // 输出:完成度:95%
常见错误场景包括生成进度报告、配置日志模板、拼接 SQL 注释等,只要字符串末尾或中间需要显式输出 %,就必须双写。
千分位分隔符在不同 Locale 下行为不一致
%,d 和 %,.2f 这类带逗号的格式符依赖当前 Locale。比如 String.format(Locale.US, "%,d", 1000000) 输出 1,000,000,但换成 Locale.CHINA 可能输出 1000000(中文环境默认不用千分位),甚至某些旧 JDK 版本下直接抛异常。
稳妥做法是显式指定 Locale.US(或 Locale.ENGLISH):
- 用
String.format(Locale.US, "%,d", 1234567)→1,234,567 - 浮点数同理:
String.format(Locale.US, "%,.2f", 1234567.891)→1,234,567.89 - 避免依赖系统默认 locale,尤其在服务器多语言环境或容器化部署中
整数加千分位再加百分号,顺序和转义容易搞混
想输出类似 12,345% 这种“数值+千分位+百分号”的组合,不能写成 "%,d%" —— 这会因缺少转义导致解析失败,也不能写成 "%,d%%"(那是 12345%,没千分位)。
关键点在于:千分位修饰符 , 必须紧贴在类型符(如 d 或 f)前面,而 %% 是独立的字面量:
String s = String.format(Locale.US, "%,d%%", 12345); // 正确:12,345%
如果用浮点数表示百分比(如 99.99%),注意先乘 100 再格式化:
double rate = 0.9999; String s = String.format(Locale.US, "%,.2f%%", rate * 100); // 99.99%
性能敏感场景下,别在循环里反复调用 String.format()
String.format() 底层会创建 Formatter 实例并解析格式串,比直接字符串拼接或 StringBuilder 慢不少。尤其在高频日志、实时计算或游戏帧循环中,"%" + value + "%" 虽丑但快;若必须格式化,考虑预编译或缓存 MessageFormat 实例。
另外,Android 上低版本(API %,d 支持不全,真机测试比文档更可靠。
千分位和百分号本身不难,难的是它们叠加时的转义优先级和 locale 隐含行为——这两个地方出错,往往连异常都看不出哪少了个 %。











