String.format 背后的格式说明符怎么解析?各种写法会得到什么、出错时抛什么?这篇用同一个小程序把几十种写法的实际输出打印出来(正则回溯在前一篇,String.format 的耗时在已有文章里)。
语法:%[参数序号$][标志][宽度][.精度]转换符(以下 Locale.US)
%d → "42"
%5d| → " 42|"
%-5d| → "42 |"
%05d → "00042"
%+d → "+42"
%,d → "1,234,567"
%x → "ff"
%X → "FFFFFFFF"
%o → "10"
%(d → "(42)"
%f → "3.141590"
%.2f → "3.14"
%8.3f → " 3.142"
%08.3f → "-003.142"
%e → "1.234568e+04"
%.3g → "0.000123"
%.0f → "3"
%.0f → "4"
%.1f → "0.3"
%.1f → "0.4"
%s → "hi"
%10s| → " hi|"
%-10s| → "hi |"
%.2s → "he"
%S → "HI"
%s → "null"
%s → "[1, 2]"
%b → "true"
%b → "false"
%c → "A"
%c → "😀"
%% → "%"
%h → "d01" %d → IllegalFormatConversionException: d != java.lang.Double
%d → IllegalFormatConversionException: d != java.lang.String
%s %s → MissingFormatArgumentException: Format specifier '%s'
%z → UnknownFormatConversionException: Conversion = 'z'
%#d → FormatFlagsConversionMismatchException: Conversion = d, Flags = #
%-d → MissingFormatWidthException: %-d
%5 → UnknownFormatConversionException: Conversion = '5'
%.2d → IllegalFormatPrecisionException: 2
%,s → FormatFlagsConversionMismatchException: Conversion = s, Flags = ,
%d → "10"
%d → "123456789012345678901234567890"
%f → IllegalFormatConversionException: f != java.lang.Integer
%d → "null"
%s → "1"
多余的参数不报错(最后一行 %s 只用了第一个);缺少参数、类型不符、格式符不认识、标志冲突才抛异常 en_US %,d → 1,234,567 %.2f → 1234.50
de_DE %,d → 1.234.567 %.2f → 1234,50
fr_FR %,d → 1 234 567 %.2f → 1234,50
hi_IN %,d → 1,234,567 %.2f → 1234.50
ar_EG %,d → ١٬٢٣٤٬٥٦٧ %.2f → ١٢٣٤٫٥٠
默认 Locale = en_CN;String.format("%.2f", 1234.5) = 1234.50(不指定 Locale 时用默认 Locale)
大写转换也受 Locale 影响:Locale(tr) 下 String.format("%S", "i") = İ,US 下 = I %2$s %1$s → "hello world"
%1$s %1$s %1$s → "echo echo echo"
%s %<s %s → "a a b"
%2$s %s %s → "y x y"
%s %2$s %s → "x y y"
%3$s → MissingFormatArgumentException: Format specifier '%3$s'
规则:普通的 %s 按顺序取参数,不受 %2$s 这种显式序号的影响;%<s 重复上一个格式符用过的参数
%n 与 \n:a\nb vs a\nb(%n 是平台的行分隔符,macOS/Linux 上是 \n)
Formattable 对象配合 %-10.3s:<自定义:flags=1,width=10,precision=3>