Java格式化輸出printf()解讀
本文通過實(shí)例詳細(xì)介紹Java格式化輸出 System.out.printf() 方法的使用、參數(shù)的含義、格式轉(zhuǎn)換符使用時的注意事項(xiàng)。
1. printf API
// 使用指定的格式字符串和參數(shù)將格式化字符串寫入入到輸出流 public PrintStream printf(String format, Object ... args) // 基于本地化環(huán)境使用指定的格式字符串和參數(shù)將格式化字符串寫入到輸出流 public PrintStream printf(Locale l, String format, Object ... args)
以上2個方法,當(dāng) format 為 null 時,拋出 NPE.
2. 參數(shù)說明
format
format 是以百分號(%) 開頭的格式說明字符串,具體格式如下
%[argument_index$][flags][width][.precision]conversion

可選的 argument_index 是十進(jìn)制整數(shù),表示參數(shù)列表中參數(shù)的位置。 第一個參數(shù)由“ 1$ ”引用,第二個由“ 2$ ” 引用 ,等等。 argument_index 必須緊跟 % 后面,并以 $ 結(jié)束。
note: 參數(shù)索引值從1開始,而不是從0開始, %1$ 對第一個參數(shù)格式化。這就避免了與0標(biāo)志混淆。
可選 flags 指定格式化輸出外觀的各種標(biāo)志。 有效標(biāo)志集取決于 conversion。
可選 width是正十進(jìn)制整數(shù),表示要寫入到輸出的字符個數(shù)(注意對于浮點(diǎn)數(shù):也包含小數(shù)點(diǎn)所占的1個字和 負(fù)數(shù)的負(fù)號所占的1個字符)。 當(dāng)實(shí)際字符數(shù)小于指定的寬度時,最前面用 flags 指定的標(biāo)志填充(若未指定,默認(rèn)用空格)。
eg: v=2.3, %5.2f 輸出 5.20 ,且前面包含1個空格。共打印5個字符,整數(shù)位1個5,1個小數(shù)點(diǎn),2個精度,長度為4,比指定的寬度少1為,用1個前導(dǎo)空格代替。
可選 precision 是一個非負(fù)十進(jìn)制整數(shù),通常用于限制字符數(shù)。 具體行為取決于轉(zhuǎn)換。
conversion (必需) 是一個字符,指示如何格式化參數(shù)。 給定參數(shù)的有效轉(zhuǎn)換集取決于參數(shù)的數(shù)據(jù)類型。
- 表1-用于printf flags(標(biāo)志) 說明
| 標(biāo)志 | 目的 | 示例 |
|---|---|---|
| + | 打印正數(shù)和負(fù)數(shù)的符號 | +3333.33 |
| 空格 | 在正數(shù)之前添加空格 | | 3333.33| |
| 0 | 數(shù)字前面補(bǔ)0 | 003333.33 |
| - | 左對齊(不指定-時,默認(rèn)為右對齊) | |3333.33 | |
| ( | 將負(fù)數(shù)括在括號內(nèi) | %d,-90輸出(90) |
| ,(英文逗號) | 添加分組分隔符,只對定點(diǎn)浮點(diǎn)數(shù)整數(shù)部分添加分組分隔符,小數(shù)部分不會添加 | 3,333.33 |
| #(對于f格式) | 包含小數(shù)點(diǎn) | 3,333. |
| #(對于x或o格式) | 添加前綴0x或0 | 0xcafe |
| $ | 指定要格式化的參數(shù)索引。例如,%1 d d %1 dx 將以十進(jìn)制和十六進(jìn)制格式打印第1個參數(shù) | 159 9F |
| < | <格式化前面說明的數(shù)值。例如, %d<%x 將以十進(jìn)制和十六進(jìn)制打印同一個值 | 159 9F |
- 表2-用于printf conversion(轉(zhuǎn)換符) 說明
| 轉(zhuǎn)換符 | 類型 | 示例 | 轉(zhuǎn)換符 | 類型 | 示例 |
|---|---|---|---|---|---|
| d | 十進(jìn)制整數(shù) | 159 | s | 字符串 | hello |
| x | 十六進(jìn)制整數(shù) | 9f | c | 字符 | H |
| o | 八進(jìn)制整數(shù) | 237 | b | 布爾 | true |
| f | 定點(diǎn)浮點(diǎn)數(shù) | 1.59e+01 | h | 散列碼 | 42628b2 |
| e | 指數(shù)浮點(diǎn)數(shù) | tx或Yx | 日期時間(T強(qiáng)制大寫) | 已經(jīng)過時,應(yīng)當(dāng)改為使用 java.time 類。 | |
| g | 通用浮點(diǎn)數(shù)(e和f中較短的一個) | —— | % | 百分號 | % |
| a | 16進(jìn)制浮點(diǎn)數(shù) | 0x1.fccdp3 | n | 與平臺有關(guān)的換行符 | —— |
補(bǔ)充1: 使用 s 轉(zhuǎn)換符格式化任意的對象
可以使用 s 轉(zhuǎn)換符格式化任意的對象。 對于實(shí)現(xiàn)了 Formattable 接口的任意對象,將調(diào)用這個對象的 formatTo 方法;否則調(diào)用 toString 方法將這個對象轉(zhuǎn)換為字符串。
補(bǔ)充2: String.format()
使用 String.format() 方法可創(chuàng)建一個格式化的字符串,而不打印輸出。
API:
public static String format(String format, Object... args) public static String format(Locale l, String format, Object... args)
參數(shù)和 printf() 中的含義相同。
表3-日期和時間的轉(zhuǎn)換符
Note: 以下格式符已經(jīng)過時,對于新的代碼,應(yīng)當(dāng)使用 java.time 包的方法。
eg:
System.out.printf("%tc",new Date()); 這條語句將用下面的格式打印當(dāng)前的日期和時間:
Mon Feb 09 18:05:19 PST 2015
下面的轉(zhuǎn)換符前面都必須用 t/T 修飾。
| 轉(zhuǎn)換符 | 類型 | 示例 |
|---|---|---|
| c | 完整的日期和時間 | Mon Feb 09 18:05:19 PST 2015 |
| F | ISO 8601日期 | 2015/2/9 |
| D | 美國格式的日期(月/日/年) | 02/09/2015 |
| T | 24小時時間 | 18:05:19 |
| r | 12小時時間 | 6:05:19 |
| R | 24小時時間,沒有秒 | 18:05 |
| Y | 4位數(shù)字的年(前面補(bǔ)0 | 2015 |
| y | 年的后兩位數(shù)字(前面補(bǔ)0) | 15 |
| C | 年的前兩位數(shù)字(前面補(bǔ)0) | 20 |
| B | 月的完整拼寫 | February |
| b或h | 月的縮寫 | Feb |
| m | 兩位數(shù)字的月(前面補(bǔ)0) | 02 |
| d | 兩位數(shù)字的日(前面補(bǔ)0) | 09 |
| e | 兩位數(shù)字的日(前面不補(bǔ)0 | 9 |
| A | 星期幾的完整拼寫 | Monday |
| a | 星期幾的縮寫 | Mon |
| j | 三位數(shù)的年中第幾天(前面補(bǔ)0),在001到366之間 | 069 |
| H | 兩位數(shù)字的小時(前面補(bǔ)0),在0到23之間 | 18 |
| k | 兩位數(shù)字的小時(前面不補(bǔ)0),在0到23之間 | 18 |
| I | 兩位數(shù)字的小時(前面補(bǔ)0),在01到12之間 | 06 |
| l | 兩位數(shù)字的小時(前面不補(bǔ)0),在1到12之間 | 6 |
| M | 兩位數(shù)字的分鐘(前面補(bǔ)0) | 05 |
| S | 兩位數(shù)字的秒(前面補(bǔ)0) | 19 |
| L | 三位數(shù)字的毫秒(前面補(bǔ)0) | 047 |
| N | 九位數(shù)字的毫微秒(前面補(bǔ)0) | 047000000 |
| p | 上午或下午的標(biāo)志 | pm |
| z | 從 GMT 起,RFC 822 數(shù)字位移 | -800 |
| Z | 時區(qū) | PST |
| s | 從格林尼治時間 1970-01-01 00:00:00 起的秒數(shù) | 1078884319 |
| Q | 從格林尼治時間 1970-01-01 00:00:00 起的毫秒數(shù) | 1078884319047 |
從上表可以看到,某些格式只給出了指定日期的部分信息。
例如,只有日期或月份。如果需要多次提供日期來分別格式化每一部分就太笨拙了。
為此,可以用一個格式字符串指示要格式化的參數(shù)索引。
索引必須緊跟在%后面,并以$終止。
例如,
System.out.printf("%1$s %2$tB %2$te, %2$tY","Due date:",new Date());會打印
Due date: February 9, 2015
還可以選擇使用<標(biāo)志。它指示前面格式說明中的參數(shù)將被再次使用。也就是說,以下語句將產(chǎn)生與前面語句同樣的輸出結(jié)果:
System.out.printf("%1$s %tB %<te, %<tY","Due date:",new Date());args
args : 格式字符串中格式說明符引用的參數(shù)。
如果參數(shù)多于格式說明符,則忽略額外參數(shù)。
參數(shù)的數(shù)量是可變的,可以為零。
參數(shù)的最大數(shù)量受The Java Virtual Machine Specification(java虛擬機(jī)規(guī)范)定義的Java數(shù)組的最大維數(shù)限制。
null參數(shù)上的行為取決于 conversion(轉(zhuǎn)換符) 。
locale
數(shù)字和日期的格式化規(guī)則是特定于本地化環(huán)境的。
例如,在德國,分組分隔符是點(diǎn)號而不是逗號,另外 Monday被格式化為 Montag。
locale主要用于如何控制應(yīng)用的國際化行為。
3.printf 使用實(shí)例
// +199 199 c7 307 0xc7 0307
System.out.printf("%+d %<d %<x %<o %<#x %<#o\n",199);
// | 23| |23|
System.out.printf("|% d| |%<d|\n",23);
// hello 第5個字符是o,that's true
System.out.printf("%s 第%d個字符是%c,that's %b\n","hello",5,'o',true);
// 15 % 6 = 3
System.out.printf("%2$d %% %1$d = %3$d\n",6,15, 15 % 6);
// | 7.33| |007.33| |7.330000| 0x1.d51eb851eb852p2
System.out.printf("|%6.2f| |%0<6.2f| |%<f| %<a\n",7.33);
// | 211.79| |211.79 |
System.out.printf("|%7.2f| |%<-7.2f|\n",211.79);
// | -211.79| |(211.79)| |(-211.79)|
System.out.printf("|%8.2f| |%<(8.2f| |(%<.2f)|\n",-211.79);
// |-21171.3333| |-21,171.3333| |-2.1171e+04| |-2.117e+04|
System.out.printf("|%.4f| |%<,.4f| |%<.4e| |%<.4g|\n",-21171.3333);
String str = new String("tree");
// Note: %h 格式符輸出對象的散列碼 和 調(diào)用對象的hashCode 得到的值并不相同
// obj %h formatinput: 36739e,hashCode:3568542
System.out.printf("obj %%h formatinput: %h,hashCode:%s\n",str,str.hashCode());
// true 25 0.0032 含
System.out.printf("%s %s %s %s\n",true,25,3.2e-3,'含');
System.out.printf("|%n| \n","world");
System.out.printf("|%n| \n");輸出
+199 199 c7 307 0xc7 0307
| 23| |23|
hello 第5個字符是o,that's true
15 % 6 = 3
| 7.33| |007.33| |7.330000| 0x1.d51eb851eb852p2
| 211.79| |211.79 |
| -211.79| |(211.79)| |(-211.79)|
|-21171.3333| |-21,171.3333| |-2.1171e+04| |-2.117e+04|
obj %h formatinput: 36739e,hashCode:3568542
true 25 0.0032 含
|
|
|
|
關(guān)于printf 轉(zhuǎn)換符使用的注意事項(xiàng)
- 適用于浮點(diǎn)類型轉(zhuǎn)換符(e,g,a,f)不能用于整形; 同樣適用于整形的轉(zhuǎn)換符(d,o,x)不能用于浮點(diǎn)型。
- 可以使用 s 轉(zhuǎn)換符格式化任意的對象。對于實(shí)現(xiàn)了 Formattable 接口的任意對象,將調(diào)用這個對象的 formatTo 方法;否則調(diào)用 toString 方法將這個對象轉(zhuǎn)換為字符串。
eg:
// test in jdk 8,11,14
// Exception in thread "main" java.util.IllegalFormatConversionException: o != java.lang.Float
System.out.printf("%o\n",2.3f);
// Exception in thread "main" java.util.IllegalFormatConversionException: f != java.lang.Integer
System.out.printf("%f\n",25);總結(jié)
以上為個人經(jīng)驗(yàn),希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
Java基于socket實(shí)現(xiàn)的客戶端和服務(wù)端通信功能完整實(shí)例
這篇文章主要介紹了Java基于socket實(shí)現(xiàn)的客戶端和服務(wù)端通信功能,結(jié)合完整實(shí)例形式分析了Java使用socket建立客戶端與服務(wù)器端連接與通信功能,需要的朋友可以參考下2018-05-05
一文帶你了解Java創(chuàng)建型設(shè)計(jì)模式之原型模式
原型模式其實(shí)就是從一個對象在創(chuàng)建另外一個可定制的對象,不需要知道任何創(chuàng)建的細(xì)節(jié)。本文就來通過示例為大家詳細(xì)聊聊原型模式,需要的可以參考一下2022-09-09
Spring Boot項(xiàng)目利用Redis實(shí)現(xiàn)session管理實(shí)例
本篇文章主要介紹了Spring Boot項(xiàng)目利用Redis實(shí)現(xiàn)session管理實(shí)例,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-06-06
Java調(diào)用參數(shù)類型是application/x-www-form-urlencoded的API問題
在使用Postman進(jìn)行接口測試時,對于POST請求,需將請求頭設(shè)置為application/x-www-form-urlencoded,并將參數(shù)轉(zhuǎn)為String類型,通常在GET請求中,參數(shù)直接拼接在URL后,本文通過具體實(shí)例,詳細(xì)講解了參數(shù)處理的方法,適合API開發(fā)者參考2024-09-09
struts1實(shí)現(xiàn)簡單的登錄功能實(shí)例(附源碼)
本篇文章主要介紹了struts1實(shí)現(xiàn)簡單的登錄功能實(shí)例(附源碼),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-04-04
springboot mybatis里localdatetime序列化問題的解決
這篇文章主要介紹了springboot mybatis里localdatetime序列化問題,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-10-10
Spring Boot整合Spring Data Jpa代碼實(shí)例
這篇文章主要介紹了Spring Boot整合Spring Data Jpa代碼實(shí)例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2019-11-11
一篇文章掌握J(rèn)ava?Thread的類及其常見方法
Thread類用于操作線程,是所以涉及到線程操作(如并發(fā))的基礎(chǔ)。本文將通過代碼對Thread類的功能作用及其常見方法進(jìn)行分析2022-03-03

