文档

Java™ 教程-Java Tutorials 中文版
自定义格式
Trail: Internationalization
Lesson: Formatting
Section: Numbers and Currencies

自定义格式

你可以使用 DecimalFormat 类将十进制数格式化为特定于语言环境的字符串。此类允许你控制前导和尾随零,前缀和后缀,分组(千)分隔符和小数分隔符的显示。如果要更改格式符号(例如小数点分隔符),可以将 DecimalFormatSymbolsDecimalFormat 类结合使用。这些类在数字格式化方面提供了极大的灵活性,但它们可以使你的代码更加复杂。

下面的文本使用演示 DecimalFormatDecimalFormatSymbols 类的示例。此材料中的代码示例来自名为 DecimalFormatDemo 的示例程序。

构建模式

使用模式 String 指定 DecimalFormat 的格式设置属性。模式决定格式化后的数字的外观。有关模式语法的完整说明,请参阅 Number Format Pattern Syntax

下面的示例通过将模式 String 传递给 DecimalFormat 构造函数来创建格式化程序。format 方法接受 double 值作为参数,并在 String 中返回格式化的数字:

DecimalFormat myFormatter = new DecimalFormat(pattern);
String output = myFormatter.format(value);
System.out.println(value + " " + pattern + " " + output);

前面的代码行的输出如下表所述。value 是要格式化的数字,double 类型。patternString,它指定格式设置属性。output,即 String,表示格式化的数字。

DecimalFormatDemo 程序输出
模式 output 解释
123456.789 ###,###.### 123,456.789 井号(#)表示一个数字,逗号是分组分隔符的占位符,句点是小数分隔符的占位符。
123456.789 ###.## 123456.79 value 在小数点右边有三位数,但 pattern 只有两位。format 方法通过四舍五入处理此问题。
123.78 000000.000 000123.780 pattern 指定前导零和尾随零,因为使用 0 字符而不是井号(#)。
12345.67 $###,###.### $12,345.67 pattern 中的第一个字符是美元符号($)。请注意,它紧接在格式化的 output 中最左边的数字之前。
12345.67 \u00A5###,###.### ¥12,345.67 pattern 使用 Unicode 值为 00A5 指定日元(¥)的货币符号。

区域敏感格式

上面的示例为默认的 Locale 创建了一个 DecimalFormat 对象。如果想要非缺省 LocaleDecimalFormat 对象,则实例化 NumberFormat,然后将其强制转换为 DecimalFormat。这是一个例子:

NumberFormat nf = NumberFormat.getNumberInstance(loc);
DecimalFormat df = (DecimalFormat)nf;
df.applyPattern(pattern);
String output = df.format(value);
System.out.println(pattern + " " + output + " " + loc.toString());

运行上一个代码示例将导致后面的输出。格式化的数字(在第二列中)随 Locale 而变化:

###,###.###      123,456.789     en_US
###,###.###      123.456,789     de_DE
###,###.###      123 456,789     fr_FR

到目前为止,这里讨论的格式模式遵循美国英语的规范。例如,在模式 ###,###.## 中,逗号是千位分隔符,句点表示小数点。如果终端用户没有接触到它,那么这个规范很好。但是,某些应用程序(如电子表格和报表生成器)允许终端用户定义自己的格式设置模式。对于这些应用程序,终端用户指定的格式模式应使用本地化表示法。在这些情况下,你需要在 DecimalFormat 对象上调用 applyLocalizedPattern 方法。

改变格式符号

你可以使用 DecimalFormatSymbols 类来更改由 format 方法生成的格式化数字中出现的符号。这些符号包括小数分隔符,分组分隔符,减号和百分号等。

下一个示例通过对数字应用奇怪的格式来演示 DecimalFormatSymbols 类。不常见的格式是调用 setDecimalSeparatorsetGroupingSeparatorsetGroupingSize 方法的结果。

DecimalFormatSymbols unusualSymbols = new DecimalFormatSymbols(currentLocale);
unusualSymbols.setDecimalSeparator('|');
unusualSymbols.setGroupingSeparator('^');

String strange = "#,##0.###";
DecimalFormat weirdFormatter = new DecimalFormat(strange, unusualSymbols);
weirdFormatter.setGroupingSize(4);

String bizarre = weirdFormatter.format(12345.678);
System.out.println(bizarre);

运行时,此示例以奇怪的格式打印数字:

1^2345|678

数字格式模式语法

你可以按照以下 BNF 图表指定的规则为数字设计自己的格式模式:

pattern    := subpattern{;subpattern}
subpattern := {prefix}integer{.fraction}{suffix}
prefix     := '\\u0000'..'\\uFFFD' - specialCharacters
suffix     := '\\u0000'..'\\uFFFD' - specialCharacters
integer    := '#'* '0'* '0'
fraction   := '0'* '#'*

上图中使用的符号如下表所示:

符号 描述
X* 0 个或更多个 X 实例
(X | Y) X 或 Y
X..Y 从 X 到 Y 的任何字符,包括在内
S - T S 中的字符,除了 T 中的字符
{X} X 是可选的

在前面的 BNF 图中,第一个子模式指定了正数的格式。第二个子模式是可选的,指定负数的格式。

虽然未在 BNF 图中注明,但逗号可能出现在整数部分内。

在子模式中,你可以使用特殊符号指定格式。这些符号如下表所述:

符号 描述
0 一个数字
# 一个数字,不存在时显示为零
. 小数分隔符的占位符
, 分组分隔符的占位符
E 为指数格式分隔尾数和指数
; 分隔格式
- 默认负前缀
% 乘以 100 并显示为百分比
? 乘以 1000,以千为单位显示
¤ 货币符号;用货币符号代替;如果是两个,用国际货币符号代替;如果存在于模式中,则使用货币小数分隔符而不是小数分隔符
X 任何其他字符都可以在前缀或后缀中使用
' 用于转义前缀或后缀中的特殊字符

Previous page: Using Predefined Formats
Next page: Dates and Times