Java中允許我們對指定的物件進行某種格式化,從而得到我們想要的格式化樣式,
Format
首先介紹java.text包中的Format
Foramt是一個抽象基類,其具體子類必須實作
format(Object obj, StringBuffer toAppendTo, FieldPosition pos)
和
parseObject(String source, ParsePosition pos)
兩個抽象方法,
format方法用于將物件格式化為指定模式的字串
parseObject方法用于將字串重新決議為物件
Format的直接子類包括DateFormat、NumberFormat和MessageFormat,下面一一進行介紹
1.DateFormat
DateFormat根據當前語言環境格式化日期和時間,DateFormat是一個抽象類,所以不能直接new創建實體物件,但該類為我們提供了工廠方法方便我們使用,
1.getDateInstance()方法,獲取格式化的日期,輸出樣式:2015-12-102.getDateTimeInstance()方法,獲取格式化的日期和時間,輸出樣式:2015-12-10 10:21:413.getTimeInstance()方法,獲取格式化的時間,輸出樣式:10:21:414.getInstance()方法,獲取格式化的日期和時間,輸出樣式:15-12-10 上午10:21
也許你會發現,在這些工廠發放中允許我們傳入一個int引數,該引數允許我們設定格式化風格,從而得到我們相對理想的結果,下表中對應了不同的style值和輸出樣式(這些常量值都在DateFormat類中)
| 樣式值 | 日期 | 時間 |
|---|---|---|
| SHORT | 15-12-10 |
上午10:08 |
| MEDIUM | 2015-12-10 |
10:09:23 |
| LONG | 2015年12月10日 |
上午10時09分40秒 |
| FULL | 2015年12月10日 星期四 |
上午10時17分30秒 CST |
| DEFAULT | 2015-12-10 |
10:18:07 |
當然你也可以指定語言環境獲取該語言環境下的格式化日期和時間,
DateFormat format = DateFormat.getDateInstance(DateFormat.DEFAULT,Locale.CANADA);//獲取加拿大的格式化日期
也許你要發問了,上面的格式沒有我一個想要的啊,那好,這里還有一個好東西
SimpleDateFormat
SimpleDateFormat是DateFormat的一個具體類,它允許我們指定格式模式從而獲取我們理想的格式化日期和時間,
通過SimpleDateFormat的構造方法你可以傳入一個格式模式字串或者通過applyPattern(String pattern)方法添加一個格式模式字串,
對于格式模式字串,API為我們提供了豐富的模式元素,下面列出幾個常用的模式元素
| 字母 | 日期或時間元素 | 示例 |
|---|---|---|
| y | 年 | 2015 |
| M | 年中的月份 | 12 |
| w | 年中的周數 | 50 |
| W | 月份中的周數 | 02 |
| D | 年中的天數 | 344 |
| d | 月份中的天數 | 10 |
| F | 月份中的星期 | 02 |
| E | 星期中的天數 | 星期四、Thu |
| a | AM/PM標記 | 下午、PM |
| H | 一天中的小時數(0~23) | 21 |
| k | 一天中的小時數(1~24) | 21 |
| K | am/pm中的小時數(0~11) | 09 |
| h | am/pm中的小時數(1~12) | 09 |
| m | 小時中的分鐘數 | 31 |
| s | 分鐘中的秒數 | 08 |
| S | 毫秒數 | 716 |
如果你設定Locale的話,會有不同的顯示格式,比如如果設定Locale.ENGLISH,E會顯示為英文格式,a顯示為AM或PM
Date date = new Date();SimpleDateFormat format = new SimpleDateFormat("今天是yyyy-MM-dd E hh:mm:ss,是yyyy年的第DD天,在該月是第dd天");System.out.println(format.format(date));
將會輸出:今天是2015-12-10 星期四 09:38:16,是2015年的第344天,在該月是第10天
2.NumberFormat
NumberFormat根據當前語言環境格式化數字NumberFormat同樣是一個抽象基類,可以使用API中的工廠方法獲取實體物件
1.getCurrencyInstance()方法,根據當前語言環境獲取貨幣數值格式,傳遞Locale物件可以獲取指定語言環境下的貨幣數值格式,比如
NumberFormat format = NumberFormat.getCurrencyInstance(Locale.CANADA);System.out.println(format.format(439.6));
將會輸出:$439.60
2.getInstance()和getNumberInstance()方法都會獲取到常規數值格式
3.getIntegerInstance()方法獲取常規整數值格式,如果需要格式化的數值為小數,則會將數值四舍五入為最接近的整數
4.getPercentInstance()方法獲取百分比的數值格式NumberFormat有兩個具體實作子類DecimalFormat和ChoiceFormat
DecimalFormat
DecimalFormat同SimpleDateFormat類似,允許我們指定格式模式獲取我們想要的格式化數值
DecimalFormat類對于數值的小數部分,默認顯示3位小數,在去掉超出小數點后面3位的部分時,會將數值四舍五入為最接近的數值格式化輸出,淡然我們可以對這個默認進行設定setMaximumFractionDigits(int newValue)方法,設定小數部分中允許的最大數字位數setMinimumFractionDigits(int newValue)方法,設定小數部分中允許的最小數字位數,如果原數小數位數不夠的話,會補零,
對于數值的整數部分,默認3個數字為一組進行顯示,同樣對此我們也可以自定義,使用setGroupingSize(int i)方法,設定分組中一組的位數,setGroupingUsed(boolean value)方法設定是否使用分組,true表示使用,false表示取消分組setMaximumIntegerDigits(int newValue)方法設定整數部分允許的最大數字位數setMinimumIntegerDigits(int newValue)方法設定整數部分允許的最小數字位數
在````的構造方法中,允許我們傳入格式模式字串輸出我們想要的格式化數值,格式模式元素包含如下
||
----|------------|------
0 | 表示一個數字,被格式化數值不夠的位數會補0
| 表示一個數字,被格式化數值不夠的位數會忽略
. | 小數點分隔符的占位符
, | 分組分隔符的占位符
-
| 預設負數前綴
% | 將數值乘以100并顯示為百分數
\u2030 | 將數值乘以1000并顯示為千分數再次
DecimalFormat format1 = new DecimalFormat("#\u2030");System.out.println(format1.format(0.3345));//輸出334‰DecimalFormat format2 = new DecimalFormat("##.##");System.out.println(format2.format(12.345));//輸出12.35DecimalFormat format3 = new DecimalFormat("0000.00");System.out.println(format3.format(12.345));//輸出0012.35DecimalFormat format4 = new DecimalFormat("#.##%");System.out.println(format4.format(12.345));//輸出1234.5%
ChoiceFormat
ChoiceFormat允許將格式化運用到某個范圍的數,通常與MessageFormat一同使用,ChoiceFormat在構造方法中接收一個format陣列和一個limits陣列,這兩個陣列的長度必須相等,例如:
limits = {1,2,3,4,5,6,7}formats = {"Sun","Mon","Tue","Wed","Thur","Fri","Sat"}
limits陣列實際上是個區間,可開可閉,并且必須按升序排列,如果不按升序排列,格式化結果將會不正確,還可以使用\u221E(表示無窮大),ChoiceFormat的匹配公式
limit[j] <= X <limit[j+1]
其中X表示使用format方法傳入的值,j表示limit陣列中的索引,當且僅當上述公式成立時,X匹配j,如果不能匹配,則會根據X是太小還是太大,匹配limits陣列的第一個索引或最后一個索引,然后使用匹配的limits陣列中的索引,去formats陣列中尋找相同索引的值,例子:
double[] limits = { 3, 4, 5, 6, 7, 8, 9 };String[] formats = { "星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期日" };ChoiceFormat format = new ChoiceFormat(limits, formats);System.out.println(format.format(2.5));//將會輸出"星期一"/**3.6介于3和4之間,所以會匹配3,又由于3在limits陣列中的索引是0,所以會在formats陣列徐照索引0的值,即輸出"星期一"*/System.out.println(format.format(3.6));
下面看一下ChoiceFormat類中的幾個常用方法
1.nextDouble(double d)靜態方法查找大于d的最小double值,用在limits陣列中,從而使limits陣列形成一個右開區間陣列,例如limits = {0,1,ChoiceFormat.nextDouble(1)}
2.nextDouble(double d, boolean positive)靜態方法,如果positive引數為true,表示查找大于d的最小double值;如果positive引數為false,表示查找小于d的最大double值,這樣就可以使limits形成一個左開區間陣列,
3.previousDouble(double d)靜態方法,查找小于d的最大double值ChoiceFormat類的構造方法也允許我們傳入一個模式字串,format方法會根據這個模式字串執行格式化操作,一個模式元素的格式如下:
doubleNum [占位符] formatStr
占位符可以使用#、< 、\u2264(<=)
ChoiceFormat cf = new ChoiceFormat("1#is 1 | 1<is more than 1");System.out.println(cf.format(1));//輸出"is 1"System.out.println(cf.format(2));//輸出"is more than 1"System.out.println(cf.format(0));//輸出"is 1"
由上面的例子可以看出,模式字串中的每個模式元素之間使用"|"分割,"|"前后可以添加空格以美化代碼,而且必須按照升序進行書寫,否則會出現java.lang.IllegalArgumentException的運行時例外,
觀看ChoiceFormat類的原始碼我們得知,實際上在內部,模式字串還是被轉換為limits和formats兩個陣列,在原始碼中
public ChoiceFormat(String newPattern) {applyPattern(newPattern);}/** applyPattern(newPattern)方法的部分原始碼*/public void applyPattern(String newPattern) {...choiceLimits = new double[count];System.arraycopy(newChoiceLimits, 0, choiceLimits, 0, count);choiceFormats = new String[count];System.arraycopy(newChoiceFormats, 0, choiceFormats, 0, count);...}
可以看出ChoiceFormat(String newPattern)呼叫了applyPattern(String newPattern)方法,在applyPattern方法中對newPattern字串進行決議,然后將決議后的資料放置到ChoiceFormat類的兩個私有屬性double[] choiceLimits和String[] choiceFormats中,然后使用格式化方法即可,
3.MessageFormat
MessageFormat提供了以語言環境無關的生成連接訊息的方式,
常用MessageFormat的靜態方法format,該方法接收一個字串的模式和一組物件(物件陣列),按照模式形式將格式化的物件插入到模式中,然后回傳字串結果,MessageFormat的格式模式元素(FormatElement)形式如下:
{ArgumentIndex}
{ArgumentIndex,FormatType}
{ArgumentIndex,FormatType,FormatStyle}
其中ArgumentIndex物件陣列中的索引,從0開始,
FormatType包括number、date、 time、choice,
FormatStyle包括short、medium、long、full、integer、currency、percent、SubformatPattern(子模式),
在MessageFormat類的內部,FormatType和FormatStyle實際上是創建格式元素的Format示例
number對應了NumberFormat,其子格式對應了DecimalFormat
date和time對應了DateFormat,其資格是對應了SimpleDateFormat
choice對應了ChoiceFormat
敢說沒有意思,來多舉幾個栗子:
你可以直接使用MessageFormat類中的靜態方法format,像這樣:
/**這是原始碼注釋中的一個例子* 在這個例子中靜態方法format第一個引數是字串型別的,* 即模式字串,第二個引數是個可變引數,實際上就是一個Object型別的陣列,* 在模式字串中使用"{}"標識一個FormatElement,"{}"中的ArgumentIndex對應Object陣列中回應索引處的值,*/int planet = 7;String event = "a disturbance in the Force";String result = MessageFormat.format("At {1,time} on {1,date}, there was {2} on planet {0,number,integer}.",planet, new Date(), event);System.out.println(result);
//輸出:At 20:39:15 on 2015-12-11, there was a disturbance in the Force on planet 7.
你也可以使用MessageFormat的構造方法傳入pattern string(模式字串),然后呼叫普通的format方法,在這里就不舉栗子了,
我們不僅被允許使用MessageFormat類中提供默認的FormatElement去format這些物件,還可以設定自己的Format物件format這些Object,
/**在這個例子中,MessageFormat和ChoiceFormat被結合使用* MessageFormat類中有3個方法值的我們關注 * 1.setFormatByArgumentIndex(int argumentIndex, Format newFormat)// * 2.setFormats(Format[] newFormats) * 3.setFormat(int formatElementIndex, Format newFormat) * 在這個例子當中,在MessageFormat的模式字串的FormatElement(即{}中的內容)中 * 索引為0的地方將使用ChoiceFormat的格式去格式化, * 如果在set的Format中仍具有FormatElement,則會遞回呼叫MessageFormat的format方法, */ MessageFormat form = new MessageFormat("The disk \"{1}\" contains {0}."); double[] filelimits = { 0, 1, 2 }; String[] filepart = { "no files", "one file", "{0,number} files" }; ChoiceFormat fileform = new ChoiceFormat(filelimits, filepart); form.setFormatByArgumentIndex(0, fileform); int fileCount = 1273; String diskName = "MyDisk"; Object[] testArgs = { new Long(fileCount), diskName }; System.out.println(form.format(testArgs)); //輸出:The disk "MyDisk" contains 1,273 files.
/**在這個例子中,MessageFormat和ChoiceFormat被結合使用* MessageFormat類中有3個方法值的我們關注* 1.setFormatByArgumentIndex(int argumentIndex, Format newFormat)//* 2.setFormats(Format[] newFormats)* 3.setFormat(int formatElementIndex, Format newFormat)* 在這個例子當中,在MessageFormat的模式字串的FormatElement(即{}中的內容)中* 索引為0的地方將使用ChoiceFormat的格式去格式化,* 如果在set的Format中仍具有FormatElement,則會遞回呼叫MessageFormat的format方法,*/MessageFormat form = new MessageFormat("The disk \"{1}\" contains {0}.");double[] filelimits = { 0, 1, 2 };String[] filepart = { "no files", "one file", "{0,number} files" };ChoiceFormat fileform = new ChoiceFormat(filelimits, filepart);form.setFormatByArgumentIndex(0, fileform);int fileCount = 1273;String diskName = "MyDisk";Object[] testArgs = { new Long(fileCount), diskName };System.out.println(form.format(testArgs));//輸出:The disk "MyDisk" contains 1,273 files.
4.String類中的format方法
format方法使用占位符進行格式化
常規型別、字符型別和數值型別的占位符格式:%[index$][標識][最小寬度][.精度]轉換符
日期和時間型別的占位符格式:%[index$][標識][最小寬度]轉換符
與引數不對應的占位符格式:%[標識][最小寬度]轉換符
其中index表示引數串列中的位置上的值
可用標識:
| 標識 | 含義 |
|---|---|
| - | 在最小寬度內左對齊,不可與0標識一起使用 |
| 0 | 若內容長度不足最小寬度,則在左邊用0來填充 |
| # | 對8進制和16進制,8進制前添加一個0,16進制前添加0x |
| + | 結果總包含一個+或-號 |
| 空格 | 正數前加空格,負數前加-號 |
| , | 只用與十進制,每3位數字間用,分隔 |
| ( | 若結果為負數,則用括號括住,且不顯示符號 |
可用轉換符:
| 轉換符 | 含義 |
|---|---|
| b | 布爾型別,只要實參為非false的布爾型別,均格式化為字串true,否則為字串false |
| n | 平臺獨立的換行符, 也可通過System.getProperty("line.separator")獲取 |
| f | 浮點數型(十進制),顯示9位有效數字,且會進行四舍五入,如99.99 |
| a | 浮點數型(十六進制) |
| e | 指數型別,如9.38e+5 |
| g | 浮點數型(比%f,%a長度短些,顯示6位有效數字,且會進行四舍五入) |
| s | 字串型別 |
| c | 字符型別 |
String result1 = String.format("小明今年%d歲,他住在%s,他的月工資有%.2f", 25,"北京市",6633.435);System.out.println(result1);//輸出:小明今年25歲,他住在北京市,他的月工資有6633.44
/*****************************************************/
double num = 123.4567899;
String result2 = String.format("%e", num);
System.out.println(result2);//輸出:1.234568e+02
總結
1.Format中的子類都是不同步,所以需要注意執行緒安全問題
2.可能在某些地方我解釋的還是不太清楚,學習最重要的是多去嘗試,多撰寫代碼測驗,如果僅僅靠看就能學會的話,那你就看吧、
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/48258.html
標籤:Java
