java中printf详解

    • 简单分析
    • Formatter类介绍与使用
    • 具体介绍下参数的用法
      • 常用操作符
      • 时间日期类
        • DateTime
        • Date
        • 有一些格式化好的格式可以直接用
      • Flag
      • 日期的示例
      • 数字的示例

1.简单分析

System.out.printf(String format, Object ... args);
  1. 首先通过System拿到静态对象public final static PrintStream out = null;,类型为PrintStream。

  2. 调用PrintStream的public PrintStream printf(String format, Object ... args)方法。

  3. 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;
    }
  1. 可以看出是通过Formatter类的format(Locale l, String format, Object … args)方法进行格式化的;

2.Formatter类介绍与使用

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 tm1 te”和“%1 tY+ 表示第几个变量,tm te tY是取日期的flag。格式字符串的其余部分是固定文本。参数列表由传递给格式字符串后的方法的所有参数组成。在上面的例子中,参数列表大小为1,由Calendar对象c组成。

标准的格式写法:

 %[argument_index$][flags][width][.precision]conversion
  • argument_index是一个十进制整数,表示参数在参数列表中的位置。 第一个参数为“1 2 ”等。
  • flags是修改输出格式的一组字符。
  • width是一个正十进制整数,表示要写入输出的最小字符数。
  • precision通常用于限制字符数的非负十进制整数。

**对于日期和时间的格式是特殊的

%[argument_index$][flags][width]conversion
  • 转换表达式是两个字符。 第一个字符是’t’或’T’。 第二个字符表示要使用的格式,如示例中的meY等

3.具体介绍下参数的用法:

常用操作符

使用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());)

Date/Time

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;

Date

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

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$"表示第几个变量。         }          }

你可能感兴趣的:(☀Java,-------【JavaSE】)