Java中允许我们对指定的对象进行某种格式化,从而得到我们想要的格式化样式。 1.FormatForamt是一个抽象基类,其具体子类必须实现 format(Object obj, StringBuffer toAppendTo, FieldPosition pos)
--用于将对象格式化为指定模式的字符串 和 parseObject(String source, ParsePosition pos)
---用于将字符串重新解析为对象 Format的直接子类包括DateFormat、NumberFormat和MessageFormat 2.DateFormat- DateFormat根据当前语言环境格式化日期和时间。
- DateFormat是一个抽象类,所以不能直接new创建实例对象。但该类为我们提供了工厂方法方便我们使用。
①工厂方法: 1.getDateInstance(),获取格式化的日期,输出:2015-12-10
2.getDateTimeInstance(),获取格式化的日期和时间,输出样式:2015-12-10 10:21:41
3.getTimeInstance(),获取格式化的时间,输出样式:10:21:41
4.getInstance(),获取格式化的日期和时间,输出样式:15-12-10 上午10:21
public static void main(String[] args) {
DateFormat df1 = DateFormat.getDateInstance();
System.out.println(df1.format(new Date())); // 2020-5-11
DateFormat df2 = DateFormat.getDateTimeInstance();
System.out.println(df2.format(new Date())); //2020-5-11 16:33:03
DateFormat df3 = DateFormat.getTimeInstance();
System.out.println(df3.format(new Date())); // 16:33:03
DateFormat df4 = DateFormat.getInstance();
System.out.println(df4.format(new Date())); // 20-5-11 下午4:33
}
②设置格式化样式 在这些工厂发放中允许我们传入一个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 df1 = DateFormat.getDateInstance(DateFormat.LONG);
System.out.println(df1.format(new Date())); // 2020年5月11日
③设置语言环境 可以指定语言环境获取该语言环境下的格式化日期和时间, //获取加拿大的格式化日期
DateFormat df5 = DateFormat.getDateInstance(DateFormat.DEFAULT, Locale.CANADA);
System.out.println(df5.format(new Date())); // 11-May-2020 3.SimpleDateFormatSimpleDateFormat是DateFormat的一个具体类,它允许我们指定格式模式从而获取我们理想的格式化日期和时间。 通过SimpleDateFormat的构造方法你可以传入一个格式模式字符串或者通过applyPattern(String pattern)方法添加一个格式模式字符串。 对于格式模式字符串,下面列出几个常用的模式元素 字母 | 日期或时间元素 | 示例 | 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 |
SimpleDateFormat sp = new SimpleDateFormat("今天是yyyy-MM-dd a E hh:mm:ss,是yyyy年的第DD天,在该月是第dd天");
System.out.println(sp.format(new Date())); // 今天是2020-05-11 下午 星期一 04:59:13,是2020年的第132天,在该月是第11天
// 设置格式化语言为英文
SimpleDateFormat sp2 = new SimpleDateFormat("今天是yyyy-MM-dd a E hh:mm:ss,是yyyy年的第DD天,在该月是第dd天",Locale.ENGLISH);
System.out.println(sp2.format(new Date())); // 今天是2020-05-11 PM Mon 04:57:37,是2020年的第132天,在该月是第11天 4.NumberFormatNumberFormat根据当前语言环境格式化数字,是一个抽象基类,可以使用工厂方法获取实例对象 ①getCurrencyInstance()方法 根据当前语言环境获取货币数值格式 ②getInstance()和getNumberInstance() 都会获取到常规数值格式 ③getIntegerInstance() 获取常规整数值格式,如果需要格式化的数值为小数,则会将数值四舍五入为最接近的整数 ④getPercentInstance() 获取百分比的数值格式 NumberFormat nf1 = NumberFormat.getCurrencyInstance(Locale.CHINA);
System.out.println(nf1.format(123.5)); // ¥123.50
NumberFormat df3 = NumberFormat.getInstance();
System.out.println(df3.format(11.5)); // 11.5
NumberFormat df4 = NumberFormat.getNumberInstance();
System.out.println(df4.format(11.6)); //11.6
NumberFormat df5 = NumberFormat.getIntegerInstance();
System.out.println(df5.format(11.6)); // 12
NumberFormat df6 = NumberFormat.getPercentInstance();
System.out.println(df6.format(0.56)); // 56% 5.DecimalFormat- 允许我们指定格式模式获取我们想要的格式化数值
- DecimalFormat类对于数值的小数部分,默认显示3位小数,在去掉超出小数点后面3位的部分时,会将数值四舍五入为最接近的数值格式化输出
①setMaximumFractionDigits(int newValue) 设置小数部分中允许的最大数字位数 ②setMinimumFractionDigits(int newValue) 置小数部分中允许的最小数字位数,如果原数小数位数不够的话,会补零 ③setGroupingSize(int i) 设置分组中一组的位数 ④setGroupingUsed(boolean value) 设置是否使用分组,true表示使用,false表示取消分组 ⑤setMaximumIntegerDigits(int newValue) 设置整数部分允许的最大数字位数 ⑥setMinimumIntegerDigits(int newValue) 设置整数部分允许的最小数字位数 - public static void main(String[] args) {
- // 默认小数位保留3位
- DecimalFormat df1 = new DecimalFormat();
- System.out.println(df1.format(1.555666)); // 1.556
- // 小数部分最大位数
- DecimalFormat df2 = new DecimalFormat();
- df2.setMaximumFractionDigits(3);
- System.out.println(df2.format(12.66554433)); // 12.666
- // 小数部分最小位数
- DecimalFormat df3 = new DecimalFormat();
- df3.setMinimumFractionDigits(4);
- System.out.println(df3.format(12.23)); // 12.2300
- // 整数部分最大位数
- DecimalFormat df4 = new DecimalFormat();
- df4.setMaximumIntegerDigits(3);
- System.out.println(df4.format(4321.1234)); // 321.123
- // 整数部分最小位数
- DecimalFormat df5 = new DecimalFormat();
- df5.setMinimumIntegerDigits(4);
- System.out.println(df5.format(321.1234)); // 0,321.123
- // 设置分组中一组的位数(数值的整数部分,默认3个数字为一组进行显示)
- DecimalFormat df6 = new DecimalFormat();
- df6.setGroupingSize(2);
- System.out.println(df6.format(10000000)); // 10,00,00,00
- // 是否使用分组,true表示使用,false表示取消分组
- DecimalFormat df7 = new DecimalFormat();
- df7.setGroupingUsed(false);
- System.out.println(df7.format(10000000)); // 10000000
- }
复制代码
⑦传入格式模式字符串输出我们想要的格式化数值 字符模式类型 | 表示类型 | 小数位是否补0 | 整数位是否补0 | 0 | 表示一个数字,被格式化数值不够的位数 | 会补0 | 整数位不足时在高位补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.35
-
- DecimalFormat format3 = new DecimalFormat("0000.00");
- System.out.println(format3.format(12.345));//输出0012.35
-
- DecimalFormat format4 = new DecimalFormat("#.##%");
- System.out.println(format4.format(12.345));//输出1234.5%
复制代码
6.ChoiceFormat将格式化运用到某个范围的数,通常与MessageFormat一同使用 ①ChoiceFormat构造方法 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 cf1 = new ChoiceFormat(limits, formats);
- // 3.4满足上面匹配公式 匹配3
- System.out.println(cf1.format(3.4)); // 星期一
- // -1不满足匹配公式, 并且小于limits区间,则匹配第一个要素3
- System.out.println(cf1.format(-1)); // 星期一
- // 10不满足匹配公式, 并且大于limits区间,则匹配第一个要素9
- System.out.println(cf1.format(10)); // 星期日
- // 3.4满足上面匹配公式 匹配7
- System.out.println(cf1.format(7)); // 星期五
复制代码③ChoiceFormat几个常用方法(区间表示) ---nextDouble(double d) 静态方法 查找大于d的最小double值,用在limits数组中,从而使limits数组形成一个右开区间数组 System.out.println(ChoiceFormat.nextDouble(3)); // 3.0000000000000004
limits = {0,1,2,,3,ChoiceFormat.nextDouble(3)} // 表示[0,3)的区间 ---previousDouble(double d) 静态方法,查找小于d的最大double值 System.out.println(ChoiceFormat.nextDouble(1)); // 0.9999999999999999
limits = {ChoiceFormat.previousDouble(1),1,2,,3} // 表示(1,3]的区间 ---nextDouble(double d, boolean positive) 静态方法,如果positive参数为true,表示查找大于d的最小double值;如果positive参数为false,表示查找小于d的最大double值,这样就可以使limits形成一个左开区间数组。 System.out.println(ChoiceFormat.nextDouble(3,true)); // 3.0000000000000004
System.out.println(ChoiceFormat.nextDouble(1,false)); // 0.9999999999999999 ---\u221E \u221E(表示无穷大) limits = {0,1,2,,3,\u221E} //表示区间[0,+∞) ④模式字符串 ChoiceFormat类的构造方法也允许我们传入一个模式字符串,format方法会根据这个模式字符串执行格式化操作。一个模式元素的格式如下: doubleNum [占位符] formatStr 占位符可以使用#、< 、\u2264(<=) 格式说明: - 模式字符串中的每个模式元素之间使用"|"分割,"|"前后可以添加空格以美化代码
- 各doubleNum必须按照升序进行书写,否则会出现java.lang.IllegalArgumentException的运行时异常。
- 根据doubleNum的数据范围 获得formatStr的值
ChoiceFormat fmt = new ChoiceFormat(
"-1#is negative| 0#is zero or fraction | 1#is one |1.0<is 1+ |2#is two |2<is more than 2.");
System.out.println("Formatter Pattern : " + fmt.toPattern());
System.out.println("Format with -INF : " + fmt.format(Double.NEGATIVE_INFINITY));
System.out.println("Format with -1.0 : " + fmt.format(-1.0));
System.out.println("Format with 0 : " + fmt.format(0));
System.out.println("Format with 0.9 : " + fmt.format(0.9));
System.out.println("Format with 1.0 : " + fmt.format(1));
System.out.println("Format with 1.5 : " + fmt.format(1.5));
System.out.println("Format with 2 : " + fmt.format(2));
System.out.println("Format with 2.1 : " + fmt.format(2.1));
System.out.println("Format with NaN : " + fmt.format(Double.NaN));
System.out.println("Format with +INF : " + fmt.format(Double.POSITIVE_INFINITY));
输出:
Format with -INF : is negative
Format with -1.0 : is negative
Format with 0 : is zero or fraction
Format with 0.9 : is zero or fraction
Format with 1.0 : is one
Format with 1.5 : is 1+
Format with 2 : is two
Format with 2.1 : is more than 2.
Format with NaN : is negative
Format with +INF : is more than 2. 实际上在内部,模式字符串还是被转换为limits和formats两个数组。在源码中: ChoiceFormat(String newPattern)调用了applyPattern(String newPattern)方法,在applyPattern方法中对newPattern字符串进行解析,然后将解析后的数据放置到ChoiceFormat类的两个私有属性double[] choiceLimits和String[] choiceFormats中,然后使用格式化方法即可。 7.MessageFormat.MessageFormat提供了以语言环境无关的生成连接消息的方式。 ①基本结构: MessageFormatPattern:
String
MessageFormatPattern FormatElement String
FormatElement: // (模式元素)
{ ArgumentIndex } // ArgumentIndex对象数组中的索引,从0开始
{ ArgumentIndex , FormatType }
{ ArgumentIndex , FormatType , FormatStyle }
FormatType: one of //()
number ---NumberFormat 其子格式对应DecimalFormat
date ---DateFormat,其子格式对应SimpleDateFormat
time ---DateFormat,其子格式对应SimpleDateFormat
choice ---ChoiceFormat
FormatStyle:
short
medium
long
full
integer
currency
percent
SubformatPattern(子模式)
---解释:
String str = "I'm not a {0}, age is {1,number,short}", height is {2,number,#.#};
在这个字符串中:
1、{0}和{1,number,short}和{2,number,#.#};都属于FormatElement,0,1,2是ArgumentIndex。
2、{1,number,short}里面的number属于FormatType,short则属于FormatStyle。
3、{1,number,#.#}里面的#.#就属于子格式模式。
指定FormatType和FormatStyle是为了生成日期格式的值、不同精度的数字、百分比类型等等。 ②使用方式 - ---1.使用MessageFormat的静态方法format
- MessageFormat.format(String pattern, Object ... arguments)
- 如:
- /**
- * 在这个例子中静态方法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.
- ---2.使用MessageFormat的构造方法传入pattern string(模式字符串),然后调用普通的format方法
- 如:
- String message = "oh, {0} is a pig";
- MessageFormat messageFormat = new MessageFormat(message);
- Object[] array = new Object[]{"ZhangSan"};
- String value = messageFormat.format(array);
- System.out.println(value); // 结果 oh, ZhangSan is a pig
- ---3.设置自己的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.
复制代码③单引号问题 a. 两个单引号才表示一个单引号,单个单引号会被省略 - String message = "oh, {0} is 'a' pig";
- Object[] array = new Object[]{"ZhangSan"};
- String value = MessageFormat.format(message, array);
- System.out.println(value); // oh, ZhangSan is a pig ,单引号被省略
- ------给字母a加上单引号,两个单引号表示实际的一个单引号 如:
- String message = "oh, {0} is ''a'' pig";
- Object[] array = new Object[]{"ZhangSan"};
- String value = MessageFormat.format(message, array);
- System.out.println(value); // oh, ZhangSan is 'a' pig
复制代码b. 单引号会使某个字符或串保持原形 - String message = "oh, '{0}' is a pig";
- Object[] array = new Object[]{"ZhangSan"};
- String value = MessageFormat.format(message, array);
- System.out.println(value); // oh, {0} is a pig 此处ZhangSan无法显示
- ---正确方式 用两个单引号''进行转义:
- String message = "oh, '{0}' is a pig";
- Object[] array = new Object[]{"ZhangSan"};
- String value = MessageFormat.format(message, array);
- System.out.println(value); // oh, ZhangSan is a pig
复制代码c. 不支持左花括号(需要单引号括起来),但支持右花括号显示 - String message = "oh, '{'{0} }is a pig";
- Object[] array = new Object[]{"ZhangSan"};
- String value = MessageFormat.format(message, array);
- System.out.println(value); // 输出 oh, {ZhangSan}is a pig
复制代码
8.String.format方法
- System.out.printf("3>7的结果是:%b %n", 3>7);
复制代码
|