System.out.printf(String format, Object ... args);
首先通过System拿到静态对象public final static PrintStream out = null;
,类型为PrintStream。
调用PrintStream的public PrintStream printf(String format, Object ... args)
方法。
printf方法内部调用了public PrintStream format(String format, Object ... args)
方法。看看format方法的内部实现。
public PrintStream format(String format, Object ... args) {
try {
synchronized (this) {
ensureOpen();
if ((formatter == null)
|| (formatter.locale() != Locale.getDefault()))
formatter = new Formatter((Appendable) this);
formatter.format(Locale.getDefault(), format, args);
}
} catch (InterruptedIOException x) {
Thread.currentThread().interrupt();
} catch (IOException x) {
trouble = true;
}
return this;
}
Formatter体系
public final class Formatter
extends Object
implements Closeable, Flushable
printf风格格式的字符串解释器。Formatter可以格式化数字,字符串和日期/时间数据等,将其以特定格式输出。通过Formattable接口提供了用于任意用户类型的限制格式化定制。
对于多线程访问,格式化器不一定是安全的。线程安全是可选的,是本课程中用户的责任。Java语言的格式化打印受C的printf的极大启发。尽管格式字符串类似于C,但是已经进行了一些自定义以适应Java语言并利用其一些功能。此外,Java格式化比C更严格;例如,如果转换与标志不兼容,将抛出异常。在C中,不适用的标志被忽略。因此,格式字符串旨在被C程序员识别,但不一定完全与C中的那些完全兼容。
//Examples for expected usage:
//先看一个简单的使用示例:
@Test
public void formatter_test(){
StringBuilder sb = new StringBuilder();
// Send all output to the Appendable object sb
//用StringBuilder构建一个Formatter,将输出传入到StringBuilder
Formatter formatter = new Formatter(sb, Locale.CHINA);
// Explicit argument indices may be used to re-order output.
//是可以重新排序的,4$即代表第四个参数
formatter.format("%4$2s %3$2s %2$2s %1$2s", "a", "b", "c", "d");
// -> " d c b a"
// Optional locale as the first argument can be used to get
// locale-specific formatting of numbers. The precision and width can be
// given to round and align the value.
//locale参数可以用来获取指定环境下的格式。
formatter.format(Locale.FRANCE, "\ne = %+10.4f", Math.E);
// -> "e = +2,7183"
// The '(' numeric flag may be used to format negative numbers with
// parentheses rather than a minus sign. Group separators are
// automatically inserted.
//( 左括号是用来格式化负数的。如果是正数,这个括号不会输出
formatter.format("\nAmount gained or lost since last statement: %(,.2f",
-1.7890);
System.out.println(sb);
// d c b a
// e = +2,7183
// Amount gained or lost since last statement: (12,345.79)
}
再来看一个时间的格式化示例:
@Test
public void calendar_test(){
Calendar c = Calendar.getInstance();
String s = String.format("Today :%1$tm %1te,%1$tY",c);
System.out.println(s);
//output:Today :04 10,2017
}
"Today :%1$tm %1te,%1$tY"
串是format方法的第一个参数。它包含三个格式说明符“%1 tm”,“%1 te”和“%1 tY”,它们指示如何处理参数以及应在文本中插入哪些参数,数字+ 表示第几个变量,tm te tY是取日期的flag。格式字符串的其余部分是固定文本。参数列表由传递给格式字符串后的方法的所有参数组成。在上面的例子中,参数列表大小为1,由Calendar对象c组成。
标准的格式写法:
%[argument_index$][flags][width][.precision]conversion
**对于日期和时间的格式是特殊的
%[argument_index$][flags][width]conversion
使用b输出false ,大写b则输出FALSE,大写方式相当于转换大写
符号 | 分类 | 描述 | 示例 |
---|---|---|---|
b,B | 通用 | 传入的参数有值就打印true,为null返回false | System.out.printf("%1$b",null);//false System.out.printf("%1$b","hello");//true |
h,H | 通用 | 如果为null,打印null,否则返回hashCode的16进制 | System.out.printf("%1$h","hell");//30cf3d System.out.printf("%1$h",null);//null |
s,S | 通用 | 如果为null,打印null,否则返回arg.toString | system.out.printf("%1$s","hell");//hell |
d | integral | 返回十进制数 | System.out.printf("%1$d",0100);//八进制-64 System.out.printf(“%1$d”,0x100);//十六进制-256 |
o | integral | 返回八进制 | |
x,X | integral | 返回十六进制 | |
f | floating | 格式化float | System.out.printf("%1$.2f",100.1234555);//100.12 ,.2表示保留几个小数,默认保留5个。System.out.printf("%1$5.2f",1.1);// 1.10 ,5表示至少显示五个字符,1.1不满5个字符,则输出" 1.10" ,加上小数点正好五个。 |
t,T | date/time | 时间格式 | 后面单独介绍 |
% | percent | 返回%号 | System.out.printf("%f%%", 1.0/3); |
输出0.333333%。 |
|n|line Separator|换行|System.out.printf(“hello%ninfo”);
hello
info|
(不要忘了加t/T,例如:System.out.printf("%1$tH",new Date());
)
conver | des |
---|---|
H | 24 小时,i.e 00 - 23 |
I | 12 小时,i.e 01 - 12 |
k | 24 小时,i.e 0 - 23 |
l | 12 小时,i.e 1 - 12 |
M | 分钟 i.e 00 - 59 |
S | 秒 i.e 00 - 60 |
L | 毫秒 i.e 000 - 999 |
N | 纳秒 i.e 000000000 - 999999999 |
p | 上午下午 i.e am pm |
s | unix时间戳,从1970 00:00:00开始 范围:Long.Min_VALUE/1000 - Long.MAX_VALUE/1000; |
Q | 毫秒 从1970 00:00开始,范围:Long.MIN_VALUE - Long.MAX_VALUE; |
conver | des |
---|---|
B | 月份全英文名. ”January”, “February”. |
b | 月份英文缩写, e.g. “Jan”, “Feb”. |
h | Same as ‘b’. |
A | 星期的英文全名, e.g. “Sunday”, “Monday” |
a | 星期的英文缩写, e.g. “Sun”, “Mon” |
‘C’ | 年份/100,如2017年则为20, i.e. 00 - 99 |
‘Y’ | 四位的年份, e.g. 2017 |
‘y’ | 两位的年份, e.g. 17 i.e. 00 - 99. |
‘j’ | 一年中的第几天, e.g. 001 - 366 |
m |第几个月,
i.e. 01 - 13.(官方文档写的13)|
|d| 一月中的第几天,
i.e. 01 - 31|
|e |一月中的第几天,
i.e. 1 - 31.|
conver | des |
---|---|
R | 格式化为 24-hour, 相当于 “%tH:%tM” , e.g. 16:16 |
T | 格式化为 24-hour, 相当于 “%tH:%tM:%tS” , e.g. 16:16:29 |
r | 格式化为 12-hour , 相当于 “%tI:%tM:%tS %Tp”, e.g 04:16:06 下午 |
D | 相当于 “%tm/%td/%ty, e.g. 04/10/17”. |
F | 相当于 “%tY-%tm-%td”, e.g. 2017-04-10 |
c | 相当于 “%ta %tb %td %tT %tZ %tY”, e.g. “Sun Jul 20 16:17:00 EDT 1969”. |
Flag | General | Character | Integral | Floating Point | Date/Time | Description |
---|---|---|---|---|---|---|
‘-‘ | y | y | y | y | y | 结果会左对齐 |
‘#’ | y | - | y | y | - | 输出带有标志位的数, 例如 System.out.printf("%1$#x",100); //0x64 |
‘+’ | - | - | y | y | - | 输出带符号的数 |
‘0’ | - | - | y | y | - | 没有的用0占位,System.out.printf("%1$06.2f",1.12345);//001.12 |
‘,’ | - | - | y | y | - | 将数字用逗号隔开,更方便看System.out.printf("%1$,.2f",12345.12345);//12,345.12 |
‘(‘ | - | - | y | y | - | 如果结果是负数,会用括号括起来,正数没有括号System.out.printf("%1$(,.2f",-12345.12345); (12,345.12) |
// %t表示格式化日期时间类型,%T是时间日期的大写形式,在%t之后用特定的字母表示不同的输出格式
Date date = new Date();
long dataL = date.getTime();
// 格式化年月日
// %t之后用y表示输出日期的年份(2位数的年,如99)
// %t之后用m表示输出日期的月份,%t之后用d表示输出日期的日号
System.out.printf("%1$ty-%1$tm-%1$td; %2$ty-%2$tm-%2$td%n", date, dataL);
// %t之后用Y表示输出日期的年份(4位数的年),
// %t之后用B表示输出日期的月份的完整名, %t之后用b表示输出日期的月份的简称
System.out.printf("%1$tY-%1$tB-%1$td; %2$tY-%2$tb-%2$td%n", date, dataL);
// 以下是常见的日期组合
// %t之后用D表示以 "%tm/%td/%ty"格式化日期
System.out.printf("%1$tD%n", date);
//%t之后用F表示以"%tY-%tm-%td"格式化日期
System.out.printf("%1$tF%n", date);
/*** 输出时间类型***/
// 输出时分秒
// %t之后用H表示输出时间的时(24进制),%t之后用I表示输出时间的时(12进制),
// %t之后用M表示输出时间的分,%t之后用S表示输出时间的秒
System.out.printf("%1$tH:%1$tM:%1$tS; %2$tI:%2$tM:%2$tS%n", date, dataL);
// %t之后用L表示输出时间的秒中的毫秒
System.out.printf("%1$tH:%1$tM:%1$tS %1$tL%n", date);
// %t之后p表示输出时间的上午或下午信息
System.out.printf("%1$tH:%1$tM:%1$tS %1$tL %1$tp%n", date);
// 以下是常见的时间组合
// %t之后用R表示以"%tH:%tM"格式化时间
System.out.printf("%1$tR%n", date);
// %t之后用T表示以"%tH:%tM:%tS"格式化时间
System.out.printf("%1$tT%n", date);
// %t之后用r表示以"%tI:%tM:%tS %Tp"格式化时间
System.out.printf("%1$tr%n", date);
/*** 输出星期***/
// %t之后用A表示得到星期几的全称
System.out.printf("%1$tF %1$tA%n", date);
// %t之后用a表示得到星期几的简称
System.out.printf("%1$tF %1$ta%n", date);
// 输出时间日期的完整信息
System.out.printf("%1$tc%n", date);
double d = 345.678;
String s = '你好!';
int i = 1234; //'%'表示进行格式化输出,'%'之后的内容为格式的定义。
System.out.printf('%f',d); //'f'表示格式化输出浮点数。
System.out.println();
System.out.printf('%9.2f',d); //'9.2'中的9表示输出的长度,2表示小数点后的位数。
System.out.println();
System.out.printf('%+9.2f',d); //'+'表示输出的数带正负号。
System.out.println();
System.out.printf('%-9.4f',d); //'-'表示输出的数左对齐(默认为右对齐)。
System.out.println();
System.out.printf('%+-9.3f',d); //'+-'表示输出的数带正负号且左对齐。
System.out.println();
System.out.printf('%d',i); //'d'表示输出十进制整数。
System.out.println();
System.out.printf('%o',i); //'o'表示输出八进制整数。
System.out.println();
System.out.printf('%x',i); //'d'表示输出十六进制整数。
System.out.println();
System.out.printf('%#x',i); //'d'表示输出带有十六进制标志的整数。
System.out.println();
System.out.printf('%s',s); //'d'表示输出字符串。
System.out.println();
System.out.printf('输出一个浮点数:%f,一个整数:%d,一个字符串:%s',d,i,s); //可以输出多个变量,注意顺序。
System.out.println();
System.out.printf(' 字符串:%2$s,%1$d的十六进制数:%1$#x',i,s); //'X$'表示第几个变量。 } 浮点数。
System.out.println();
System.out.printf('%9.2f',d);//'9.2'中的9表示输出的长度,2表示小数点后的位数。
System.out.println();
System.out.printf('%+9.2f',d); //'+'表示输出的数带正负号。
System.out.println();
System.out.printf('%-9.4f',d);//'-'表示输出的数左对齐(默认为右对齐)。
System.out.println();
System.out.printf('%+-9.3f',d); //'+-'表示输出的数带正负号且左对齐。
System.out.println();
System.out.printf('%d',i); //'d'表示输出十进制整数。
System.out.println();
System.out.printf('%o',i); //'o'表示输出八进制整数。
System.out.println();
System.out.printf('%x',i); //'d'表示输出十六进制整数。
System.out.println();
System.out.printf('%#x',i); //'d'表示输出带有十六进制标志的整数。 System.out.println(); System.out.printf('%s',s); //'d'表示输出字符串。 System.out.println(); System.out.printf('输出一个浮点数:%f,一个整数:%d,一个字符串:%s',d,i,s); //可以输出多个变量,注意顺序。
System.out.println();
System.out.printf(' 字符串:%2$s,%1$d的十六进制数:%1$#x',i,s); //'X$'表示第几个变量。 } }
//定义一些变量,用来格式化输出。
double d = 345.678;
String s = "你好!";
int i = 1234; //"%"表示进行格式化输出,"%"之后的内容为格式的定义。
System.out.printf("%f",d);//"f"表示格式化输出浮点数。
System.out.println();
System.out.printf("%9.2f",d);//"9.2" 中的9表示输出的长度,2表示小数点后的位数。 System.out.println();
System.out.printf("%+9.2f",d);//"+" 表示输出的数带正负号。
System.out.println();
System.out.printf("%-9.4f",d);//"-" 表示输出的数左对齐(默认为右对齐)。
System.out.println();
System.out.printf("%+-9.3f",d);//"+-" 表示输出的数带正负号且左对齐。
System.out.println();
System.out.printf("%d",i);//"d"表示输出十进制整数。
System.out.println();
System.out.printf("%o",i);//"o"表示输出八进制整数。
System.out.println();
System.out.printf("%x",i);//"d"表示输出十六进制整数。
System.out.println();
System.out.printf("%#x",i);//"d" 表示输出带有十六进制标志的整数。
System.out.println();
System.out.printf("%s",s);//"d"表示输出字符串。
System.out.println();
System.out.printf("输出一个浮点数:%f,一个整数:%d,一个字符串:%s",d,i,s); //可以输出多个变量,注意顺序。
System.out.println();
System.out.printf("字符串:%2$s,%1$d的十六进制数:%1$#x",i,s); //"X$"表示第几个变量。 } }