1. 概述
在金融应用中处理货币代码及其对应符号至关重要。像 USD 或 EUR 这样的货币代码适用于交易处理,但用户通常更习惯看到 $ 或 € 这样的符号以提高可读性。在 Java 中正确显示货币符号并非易事,尤其需要考虑本地化场景时。
Java 提供了多种货币代码到符号的映射方案,包括内置的 Currency 类、硬编码 Map 和 Locale 支持。 本文将深入探讨这些实现方式,并附带性能对比和 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。