1. 概述

在本教程中,我们将通过多个示例展示如何使用 Java 中的 printf() 方法来格式化输出。

该方法属于 java.io.PrintStream 类,其功能类似于 C 语言中的 printf() 函数,用于格式化字符串输出。

2. 语法

我们可以使用以下两种 PrintStream 方法来格式化输出:

System.out.printf(format, arguments);
System.out.printf(locale, format, arguments);

其中,format 参数用于指定格式化规则。这些规则以 % 字符开头。

来看一个简单的例子,快速感受一下:

System.out.printf("Hello %s!%n", "World");

输出结果如下:

Hello World!

如上所示,格式字符串中包含普通文本和两个格式化规则。第一个规则用于格式化字符串参数,第二个规则用于在字符串末尾添加换行符。

2.1. 格式规则详解

我们再深入看一下格式字符串的结构。它由字面量和格式说明符组成。格式说明符按如下顺序包含标志(flags)、宽度(width)、精度(precision)以及转换字符(conversion character):

%[flags][width][.precision]conversion-character

括号中的部分是可选的。

在内部,printf() 使用 java.util.Formatter 类来解析格式字符串并生成输出。更多格式字符串选项可以参考 Formatter Javadoc

2.2. 转换字符

转换字符是必须的,它决定了参数如何被格式化。

不同转换字符只对特定的数据类型有效。常见的一些包括:

  • s:格式化字符串
  • d:格式化十进制整数
  • f:格式化浮点数
  • t:格式化日期/时间值

我们将在后续章节中进一步探讨这些转换字符及其他内容。

2.3. 可选修饰符

[flags] 用于定义标准的输出修改方式,常用于整数和浮点数的格式化。

[width] 用于指定输出字段的最小宽度,即至少输出多少个字符。

[.precision] 用于指定浮点数的小数位数,也可以用于定义从字符串中提取的子串长度。

3. 换行符

要将字符串分行输出,可以使用 %n 格式说明符

System.out.printf("baeldung%nline%nterminator");

输出结果为:

baeldung
line
terminator

⚠️ %n 是平台无关的换行符,printf() 会自动插入当前系统对应的换行符。

4. 布尔值格式化

格式化布尔值时,使用 %b 格式说明符。

根据 官方文档 的说明:

  • 如果参数为 null,则输出 "false"
  • 如果参数是 booleanBoolean 类型,则输出 String.valueOf(arg) 的结果
  • 其他情况均输出 "true"

示例代码如下:

System.out.printf("%b%n", null);
System.out.printf("%B%n", false);
System.out.printf("%B%n", 5.3);
System.out.printf("%b%n", "random text");

输出结果为:

false
FALSE
TRUE
true

✅ 注意:使用 %B 可以将结果转为大写。

5. 字符串格式化

格式化字符串时,使用 %s 同样支持大写转换:

System.out.printf("'%s' %n", "baeldung");
System.out.printf("'%S' %n", "baeldung");

输出结果为:

'baeldung' 
'BAELDUNG'

还可以通过指定宽度来控制最小长度:

System.out.printf("'%15s' %n", "baeldung");

输出为:

'       baeldung'

如果需要左对齐,可以使用 - 标志:

System.out.printf("'%-10s' %n", "baeldung");

输出为:

'baeldung  '

此外,可以通过精度来限制输出的字符数:

System.out.printf("%2.2s", "Hi there!");

语法 %x.ys 中,x 是填充宽度,y 是字符数。

示例输出为:

Hi

6. 字符格式化

使用 %c 可以输出 Unicode 字符:

System.out.printf("%c%n", 's');
System.out.printf("%C%n", 's');

大写 C 会将字符转为大写:

s
S

⚠️ 如果传入无效参数,Formatter 会抛出 IllegalFormatConversionException 异常。

7. 数字格式化

7.1. 整数格式化

printf() 方法支持所有整数类型 —— byteshortintlongBigInteger,使用 %d 进行格式化:

System.out.printf("simple integer: %d%n", 10000L);

输出结果为:

simple integer: 10000

如果需要千位分隔符,可以使用 , 标志,并且可以指定不同的区域设置:

System.out.printf(Locale.US, "%,d %n", 10000);
System.out.printf(Locale.ITALY, "%,d %n", 10000);

输出结果为:

10,000 
10.000

7.2. 浮点数格式化

格式化浮点数使用 %f

System.out.printf("%f%n", 5.1473);

输出结果为:

5.147300

可以控制精度:

System.out.printf("'%5.2f'%n", 5.1473);

这里定义宽度为 5,小数部分为 2 位:

' 5.15'

输出前有一个空格作为填充。

如果需要科学计数法,使用 %e

System.out.printf("'%5.2e'%n", 5.1473);

输出为:

'5.15e+00'

8. 日期和时间格式化

日期和时间的格式化需要两个字符:tT + 转换后缀。

对于更复杂的格式化,推荐使用 Java 8 引入的 DateTimeFormatter

8.1. 时间格式化

以下是常见的时间格式化后缀:

  • H, M, S:分别提取小时、分钟、秒
  • L, N:毫秒和纳秒
  • p:a.m./p.m. 格式
  • z:时区偏移量

示例:

Date date = new Date();
System.out.printf("%tT%n", date);

输出为:

13:51:15

更详细的时间格式:

System.out.printf("hours %tH: minutes %tM: seconds %tS%n", date, date, date);

输出为:

hours 13: minutes 51: seconds 15

为了避免重复参数,可以使用索引引用:

System.out.printf("%1$tH:%1$tM:%1$tS %1$tp %1$tL %1$tN %1$tz %n", date);

输出为:

13:51:15 pm 061 061000000 +0400

8.2. 日期格式化

常用的日期格式化后缀包括:

  • A:星期几全名
  • d:两位数的日期
  • B:月份全名
  • m:两位数的月份
  • Y:四位数年份
  • y:年份后两位

示例:

System.out.printf("%1$tA, %1$tB %1$tY %n", date);

输出为:

Thursday, November 2018

若要全部用数字格式:

System.out.printf("%1$td.%1$tm.%1$ty %n", date);

输出为:

22.11.18

9. 总结

本文介绍了如何使用 PrintStream#printf 方法来格式化输出,涵盖了各种常见数据类型的格式化方式。

相关代码示例可以在 GitHub 上找到。


原始标题:Formatting Output with printf() in Java