You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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的输出格式:

  1. 强制使用拉丁数字系统:构建Locale时指定使用拉丁数字(0-9);
  2. 明确设置格式的前缀后缀:取消原代码中交换前缀后缀的逻辑,直接指定数字在前、货币符号在后。

修改后的代码

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 21:15:19