1. 概述
String.format()
方法根据预设规则格式化字符串并返回结果。本文将深入解析该方法的语法、基础与高级用法、常见异常及最佳实践。
2. 方法语法
String.format()
提供两种重载形式:
public static String format (String format, Object... args)
public static String format (Locale l, String format, Object... args)
参数说明:
format
(String类型):格式字符串args
(Object类型):格式字符串中引用的参数l
(Locale类型):指定格式化使用的区域设置
⚠️ 关键规则:
args
数量必须与格式说明符数量匹配,多余参数会被忽略- 默认情况下,参数顺序需与格式说明符顺序严格对应
- 支持通过索引引用参数(如
%1$s
引用第一个参数),实现参数重排序或复用
示例:使用区域设置
String result = String.format(Locale.FRANCE, "Value: %.2f", 1234.5678);
3. 格式说明符
格式说明符语法因数据类型而异,但必须包含转换符。常见转换符:
转换符 | 说明 | 示例输入 | 输出 |
---|---|---|---|
%b |
布尔值 | true | "true" |
%c |
单个字符 | 'A' | "A" |
%d |
十进制整数 | 255 | "255" |
%x |
十六进制整数 | 255 | "ff" |
%f |
浮点数 | 123.456 | "123.456" |
%e |
科学计数法 | 123.456 | "1.234560e+02" |
⚠️ null值处理:%s
和 %S
转换符遇到 null 参数会输出 "null"
4. 基础用法
通过JUnit测试演示常见用法:
@Test
public void whenFormat_thenCorrect() {
String value = "Baeldung";
String formatted = String.format("Welcome to %s!", value);
assertEquals("Welcome to Baeldung!", formatted);
boolean boolValue = true;
String formattedBool = String.format("Boolean: %b", boolValue);
assertEquals("Boolean: true", formattedBool);
char charValue = 'A';
String formattedChar = String.format("Character: %c", charValue);
assertEquals("Character: A", formattedChar);
int intValue = 255;
String formattedInt = String.format("Decimal: %d", intValue);
assertEquals("Decimal: 255", formattedInt);
String formattedHex = String.format("Hex: %x", intValue);
assertEquals("Hex: ff", formattedHex);
double floatValue = 123.456789;
String formattedFloat = String.format("Float: %.2f", floatValue);
assertEquals("Float: 123.46", formattedFloat);
String formattedExponential = String.format("Exponential: %e", floatValue);
assertEquals("Exponential: 1.234568e+02", formattedExponential);
}
✅ 多格式符组合:
String multipleFormat = String.format(
"Boolean: %b, Character: %c, Decimal: %d, Hex: %x, Float: %.2f, Exponential: %e",
boolValue, charValue, intValue, intValue, floatValue, floatValue
);
assertEquals("Boolean: true, Character: A, Decimal: 255, Hex: ff, Float: 123.46, Exponential: 1.234568e+02",
multipleFormat);
5. 异常处理
5.1. 不兼容的标志
当格式符使用不兼容标志时抛出 FormatFlagsConversionMismatchException
:
@Test
public void whenIncompatibleFlags_thenFormatFlagsConversionMismatchExceptionThrown() {
assertThrows(FormatFlagsConversionMismatchException.class, () -> {
String formatted = String.format("%+s", "Baeldung"); // 字符串不支持+标志
});
}
5.2. 精度类型不匹配
对不支持精度的类型使用精度时抛出 IllegalFormatPrecisionException
:
@Test
public void whenInvalidPrecisionForType_thenIllegalFormatPrecisionExceptionThrown() {
assertThrows(IllegalFormatPrecisionException.class, () -> {
String formatted = String.format("%.2d", 123); // 整数不支持精度
});
}
5.3. 参数数量不匹配
格式符数量超过参数数量时抛出 MissingFormatArgumentException
:
@Test
public void whenMissingFormatArgument_thenMissingFormatArgumentExceptionThrown() {
assertThrows(MissingFormatArgumentException.class, () -> {
String formatted = String.format("Welcome to %s and %s!", "Baeldung"); // 缺少第二个参数
});
}
6. 整数前补零
6.1. 基础实现
补零工具方法:
private String padIntegerWithZeros(int number, int width) {
return String.format("%0" + width + "d", number);
}
格式符解析:
%
:格式符起始符0
:用0补位<width>
:最小输出宽度d
:十进制整数转换
6.2. 正负数处理
@Test
public void givenAnInteger_whenPaddingWithZeros_thanIntegerGetsPadded() {
assertEquals("00000001", padIntegerWithZeros(1, 8));
assertEquals("-0000001", padIntegerWithZeros(-1, 8)); // 负号保留,补零在符号后
}
6.3. 常见坑点
⚠️ 类型转换异常:错误使用转换符会导致 IllegalFormatConversionException
- ❌ 错误示例:
String.format("%s", 123)
(整数用字符串格式符) - ✅ 正确做法:始终使用
%d
处理整数
7. 区域化格式化
7.1. 数字格式
不同区域的千分位/小数点分隔符:
@Test
public void whenNumberFormatWithLocales_thenCorrect() {
String frenchFormatted = String.format(Locale.FRANCE, "%,f", 1234567.89);
assertEquals("1 234 567,890000", frenchFormatted); // 法国用空格作千分位
String germanFormatted = String.format(Locale.GERMANY, "%,.2f", 1234567.89);
assertEquals("1.234.567,89", germanFormatted); // 德国用点作千分位
}
7.2. 日期格式
@Test
public void whenDateFormatWithLocales_thenCorrect() {
LocalDate date = LocalDate.of(2023, 9, 30);
DateTimeFormatter usFormatter = DateTimeFormatter.ofPattern("MM/dd/yyyy", Locale.US);
String usFormatted = date.format(usFormatter);
assertEquals("09/30/2023", usFormatted);
DateTimeFormatter germanFormatter = DateTimeFormatter.ofPattern("dd.MM.yyyy", Locale.GERMANY);
String germanFormatted = date.format(germanFormatter);
assertEquals("30.09.2023", germanFormatted);
}
7.3. 货币格式
@Test
public void whenCurrencyFormatWithLocales_thenCorrect() {
NumberFormat usCurrencyFormat = NumberFormat.getCurrencyInstance(Locale.US);
String usFormatted = usCurrencyFormat.format(1000);
assertEquals("$1,000.00", usFormatted);
NumberFormat frenchCurrencyFormat = NumberFormat.getCurrencyInstance(Locale.FRANCE);
String frenchFormatted = frenchCurrencyFormat.format(1000);
assertEquals("1 000,00 €", frenchFormatted); // 法国货币符号在后
}
8. 总结
本文系统介绍了 String.format()
的核心用法:
- 基础语法与格式符规则
- 参数绑定与区域化处理
- 常见异常场景与解决方案
- 实用技巧(如补零、多类型组合)
完整示例代码见 GitHub项目。掌握这些技巧能显著提升字符串处理效率,避免常见的格式化陷阱。