Java8迁移至Java17时的货币格式化兼容问题
在Java 17中保留Java 8的阿联酋货币格式化输出格式
现有一段Java代码用于格式化阿联酋迪拉姆货币,在Java 8中输出为 Arabic Amount is: 10إ.د,但升级到Java 17后输出变为 Arabic Amount is: إ.د١٠。需要调整代码,让Java 17环境下输出与Java 8一致。
原测试代码
public class TestCurrency { public static void main(String []args) { int decimalPrecision=0; String currencySymbol="إ.د"; String dfSymbolReplacePattern = "د.إ.\u200F"; Locale locale = new Locale.Builder().setLanguage("ar").setRegion("AE").build(); final NumberFormat nf = NumberFormat.getCurrencyInstance(locale); final DecimalFormat df = (DecimalFormat) nf; df.setMinimumFractionDigits(decimalPrecision); df.setMaximumFractionDigits(decimalPrecision); df.setRoundingMode(RoundingMode.HALF_UP); final String positivePrefix = df.getPositiveSuffix().replace(dfSymbolReplacePattern, currencySymbol); final String positiveSuffix = df.getPositivePrefix().replace(dfSymbolReplacePattern, currencySymbol); final String negativePrefix = df.getNegativeSuffix().replace(dfSymbolReplacePattern, currencySymbol); final String negativeSuffix = df.getNegativePrefix().replace(dfSymbolReplacePattern, currencySymbol); df.setPositivePrefix(positivePrefix); df.setNegativePrefix(negativePrefix); df.setPositiveSuffix(positiveSuffix); df.setNegativeSuffix(negativeSuffix); System.out.println("Arabic Amount is: "+df.format(10.0)); } }
问题原因
Java 17对本地化规则和DecimalFormat的默认行为做了两处关键调整:
- 默认使用阿拉伯-Indic数字系统,输出
١٠而非Java 8的10; - 货币符号与数字的默认顺序反转,变为符号在前、数字在后。
解决方案
通过两个关键修改恢复Java 8的输出格式:
- 强制使用拉丁数字系统:构建Locale时指定使用拉丁数字(0-9);
- 明确设置格式的前缀后缀:取消原代码中交换前缀后缀的逻辑,直接指定数字在前、货币符号在后。
修改后的代码
import java.math.RoundingMode; import java.text.DecimalFormat; import java.text.NumberFormat; import java.util.Locale; public class TestCurrency { public static void main(String[] args) { int decimalPrecision = 0; String currencySymbol = "إ.د"; // 构建Locale时指定拉丁数字系统,避免输出阿拉伯-Indic数字 Locale locale = new Locale.Builder() .setLanguage("ar") .setRegion("AE") .setUnicodeLocaleKeyword("nu", "latn") .build(); final NumberFormat nf = NumberFormat.getCurrencyInstance(locale); final DecimalFormat df = (DecimalFormat) nf; df.setMinimumFractionDigits(decimalPrecision); df.setMaximumFractionDigits(decimalPrecision); df.setRoundingMode(RoundingMode.HALF_UP); // 直接设置格式规则:数字在前,货币符号在后 df.setPositivePrefix(""); df.setPositiveSuffix(currencySymbol); // 补充负数格式设置,保证负数值输出符合预期 df.setNegativePrefix("-"); df.setNegativeSuffix(currencySymbol); System.out.println("Arabic Amount is: " + df.format(10.0)); System.out.println("Arabic Negative Amount is: " + df.format(-10.0)); } }
代码说明
setUnicodeLocaleKeyword("nu", "latn"):强制Locale使用拉丁数字系统,确保输出10而非١٠;- 直接设置
positivePrefix为空、positiveSuffix为货币符号,保证数字在前、符号在后,与Java 8输出一致; - 补充负数格式配置,确保负数值输出为
-10إ.د,保持格式统一。
输出结果
Java 17环境下运行后输出:
Arabic Amount is: 10إ.د Arabic Negative Amount is: -10إ.د
内容的提问来源于stack exchange,提问作者codly
相关产品推荐
相关产品推荐

