1. 概述

在金融应用中处理货币代码及其对应符号至关重要。像 USD 或 EUR 这样的货币代码适用于交易处理,但用户通常更习惯看到 $ 或 € 这样的符号以提高可读性。在 Java 中正确显示货币符号并非易事,尤其需要考虑本地化场景时。

Java 提供了多种货币代码到符号的映射方案,包括内置的 Currency 类、硬编码 MapLocale 支持。 本文将深入探讨这些实现方式,并附带性能对比和 JUnit 测试验证。

2. 货币代码到符号的映射方案

根据本地化需求、一致性要求和维护便捷性,应用需要采用不同方式获取货币符号。以下章节将详细分析这些方法。

2.1. 使用 Currency

Java 提供了 Currency 类来获取基于 ISO 4217 标准的货币符号。该类位于 util 包中

public class CurrencyUtil {
    public static String getSymbol(String currencyCode) {
        Currency currency = Currency.getInstance(currencyCode);
        return currency.getSymbol();
    }
}

实现中,我们传入货币代码参数,通过 getInstance() 获取对应的 Currency 实例,再用 getSymbol() 获取符号。

验证 Currency 类能否正确返回符号,无效代码应抛出异常:

class CurrencyUtilTest {
    @Test
    void givenValidCurrencyCode_whenGetSymbol_thenReturnsCorrectSymbol() {
        assertEquals("$", CurrencyUtil.getSymbol("USD"));
        assertEquals("€", CurrencyUtil.getSymbol("EUR"));
    }

    @Test
    void givenInvalidCurrencyCode_whenGetSymbol_thenThrowsException() {
        assertThrows(IllegalArgumentException.class, () -> CurrencyUtil.getSymbol("INVALID"));
    }
}

2.2. 结合 Locale 使用 Currency

应用可结合 Locale 类与 Currency 类获取本地化货币符号。此方案特别适合需要根据用户区域动态调整符号的国际化应用:

public class CurrencyLocaleUtil {
    public String getSymbolForLocale(Locale locale) {
        Currency currency = Currency.getInstance(locale);
        return currency.getSymbol();
    }
}

getSymbolForLocale() 方法基于提供的区域设置获取货币符号。

验证系统是否能根据 Locale 正确返回符号:

class CurrencyLocaleUtilTest {
    private final CurrencyLocaleUtil currencyLocale = new CurrencyLocaleUtil();

    @Test
    void givenLocale_whenGetSymbolForLocale_thenReturnsLocalizedSymbol() {
        assertEquals("$", currencyLocale.getSymbolForLocale(Locale.US));
        assertEquals("€", currencyLocale.getSymbolForLocale(Locale.FRANCE));
    }
}

2.3. 使用硬编码 Map

预定义的 Map 提供了一种简单灵活的方式来显式控制货币符号映射。此方案特别适用于:

  • 需要在 UI 中显示一致符号的场景
  • 处理非常见货币
  • 强制独立于区域设置的特殊格式规则

当支持的货币集有限且不常变更时效果最佳:

public class CurrencyMapUtil {
    private static final Map<String, String> currencymap = Map.of(
        "USD", "$",
        "EUR", "€",
        "INR", "₹"
    );

    public static String getSymbol(String currencyCode) {
        return currencymap.getOrDefault(currencyCode, "Unknown");
    }
}

测试验证硬编码 Map 对已知代码返回正确符号,未知代码返回 "Unknown":

class CurrencyMapUtilTest {
    @Test
    void givenValidCurrencyCode_whenGetSymbol_thenReturnsCorrectSymbol() {
        assertEquals("$", CurrencyMapUtil.getSymbol("USD"));
        assertEquals("€", CurrencyMapUtil.getSymbol("EUR"));
        assertEquals("₹", CurrencyMapUtil.getSymbol("INR"));
    }

    @Test
    void givenInvalidCurrencyCode_whenGetSymbol_thenReturnsUnknown() {
        assertEquals("Unknown", CurrencyMapUtil.getSymbol("XYZ"));
    }
}

3. 方案对比

各方案特点不同,下表对比了适用场景和维护成本:

方案 维护成本 适用场景
Currency 无需手动更新 ✅ 支持本地化的标准应用
硬编码 Map 需手动更新 ⚠️ 需完全控制符号或处理自定义符号时
Locale 方案 无需手动更新 ✅ 国际化应用首选

选择建议:

  • 需要固定符号集?→ 硬编码 Map 最优
  • 需要本地化支持?→ Currency 类或 Locale 方案更合适

4. 总结

选择合适方案取决于具体需求:

  • 可靠性Currency 类是标准之选
  • 固定符号集:硬编码 Map 最优
  • 区域适配Locale 方案是国际化应用理想选择

决策需综合考量:

  • 本地化需求
  • 符号一致性要求
  • 维护便捷性

本文示例代码已托管至 GitHub


原始标题:Currency Code to Currency Symbol Mapping in Java | Baeldung