在Java中,为什么小数分隔符遵循Locale的语言,而不是其国家/地区,更重要的是,如何覆盖它?

我正在开展一个国际项目,并且观察到,在Java中,小数分隔符的选择基于Locale的语言,而不是其国家。 例如:

DecimalFormat currencyFormatter = (DecimalFormat) NumberFormat.getInstance(new Locale("it","IT")); System.out.println(currencyFormatter.format(-123456.78)); currencyFormatter = (DecimalFormat) NumberFormat.getInstance(new Locale("en","IT")); System.out.println(currencyFormatter.format(-123456.78)); 

产生以下输出:

 -123.456,78 -123,456.78 

我原本期望它跟随这个国家,因为如果我在国内,无论我说英语还是意大利语,那个国家的数字都用小数点分隔符写成逗号。

我的问题是双重的:

  1. 有谁知道为什么这种行为遵循语言?
  2. 更重要的是,任何人都可以提供有关如何修改Java中的默认行为以遵循该语言的详细信息吗?

谢谢。

很可能你的系统上没有已知的“en_IT”语言环境,并且Java知道没有这样的语言环境。

因此,您将获得最接近匹配的Locale的资源,根据Locale的JavaDoc中的这个注释:

当您要求特定区域设置的资源时,您将获得最佳可用匹配,而不一定是您要求的。 有关更多信息,请查看ResourceBundle

ResourceBundle中的相关文档显示,从未尝试过单独的国家/地区作为查找给定资源的标识符。 仅使用语言,语言+国家和语言+国家+变体。

1.-有谁知道为什么这种行为遵循语言?

应用程序根据其语言环境进行更改的第一个方面之一是语言。 想想瑞士,他们将法语和德语作为官方语言。 在这种情况下使用国家是没有意义的,因为除了货币之外还有其他方面(例如显示消息,要考虑)

同样适用于许多国家(加拿大是其他我想到的国家)。

该国可以选择专门使用该语言。

由于没有“意大利语英语”en_IT没有多大意义。 所以它需要“英语”,这就是为什么返回的实例是“en”英语的实例。

2.-更重要的是,任何人都可以提供有关如何修改Java中的默认行为以遵循该语言的详细信息吗?

你的意思是,这个国家对吗?

答案在于方法: NumberFormat.getAvailableLocales() ,它反过来引导您: NumberFormatProvider这是一个抽象类,您可以扩展为返回“en_IT”的正确NumberFormat (几乎将返回it_IT)

如何安装这个新类超出了我的知识,但我认为你必须在jre目录中的某个地方破解它。

编辑

因为我怀疑这个类应该安装在jre/ext文件夹下,就是这样。

在其他地方有一个项目做了类似于支持“gl_ES”的事情(加利西亚语)

以下是有关如何安装以及它的全部内容的说明:

http://www.javagalician.org/install.html

所以,基本上,如果你想为意大利提供一堆实例(或者更好的是一个实例),你只需要创建一个NumberFormatProvider实例并让它响应所有可用的语言。

但如果你是一个住在意大利的英国人,你很可能仍然用英文的方式写下你的数字,并用脑袋计算你的钱 – 反之亦然;-)

所以对我来说,这种行为看起来很合乎逻 而且我担心可能没有办法得到你想要的东西:-(

根据Oscar Reyes的评论进行更新:在Java 6中,NumberFormatProvider使您能够实现目标。

修改所有Java是一个很大的顺序; 据我所知,在JVM级别没有办法做到这一点。 但是,您可以使用DecimalFormatSymbols类手动将特定类/项目的数字格式设置为几乎任何区域设置(甚至是虚构系统)。 有关示例和更多信息,请参阅Java Tutorials页面上的 “更改格式符号”, 格式自定义 。

当然,如果您的程序可能在三个或四个以上的不同位置使用,这不是最佳方法,但如果您只支持少数几个,它可能会有效。

你的假设“我原本希望它跟随这个国家,因为如果我在国内,无论我说英语还是意大利语,那个国家的数字都用小数点分隔符作为逗号。” 是错的。 几个双语国家/地区对数字具有特定语言格式规则 在Sun的JDK中具有格式规则的国家/地区中,这适用于加拿大,印度和卢森堡。

我认为您可以使用LocaleServiceProvider覆盖每个Locale的NumberFormat行为。 这需要Java 6,但……

正如人们所指出的那样,问题很可能是java无法找到你确切的本地,所以它去了它认为最接近的地方。 如果您有一个DecimalFormat对象,可以根据需要手动更改分隔符。

 DecimalFormat format = ...; DecimalFormatSymbols symbols = format.getDecimalFormatSymbols(); symbols.setDecimalSeparator(','); symbols.setGroupingSeparator('.'); format.setDecimalFormatSymbols(symbols); 

我原本期望它跟随这个国家,因为如果我在国内,无论我说英语还是意大利语,那个国家的数字都用小数点分隔符写成逗号。

没有。一些拥有许多官方语言的国家(如加拿大(两种官方语言))根据语言有不同的格式约定:

 -1 234,56 (Locale.CANADA_FRENCH) -1,234.56 (Locale.CANADA (should probably be named CANADA_ENGLISH))