1. Overview
Handling currency codes and their corresponding symbols is essential in financial applications. Currency codes like USD or EUR are useful for transactions. However, users often prefer seeing symbols like $ or € for better readability. Displaying the correct currency symbol in Java isn’t always straightforward, especially when considering localization.
Java offers multiple ways to map a currency code to its respective symbol, including the built-in Currency class, a hardcoded Map, and Locale support. This article thoroughly explores all these approaches, along with performance comparisons and JUnit tests for validation.
2. Approaches for Currency Code to Symbol Mapping
Applications require different approaches to retrieve currency symbols depending on localization needs, consistency requirements, and ease of maintenance. The following sections explore these methods in detail.
2.1. Using the Currency Class
Java provides the Currency class to retrieve currency symbols based on ISO 4217 currency codes. It’s defined in the util package:
public class CurrencyUtil {
public static String getSymbol(String currencyCode) {
Currency currency = Currency.getInstance(currencyCode);
return currency.getSymbol();
}
}
In this implementation, we pass a currency code as a parameter and retrieve the corresponding Currency class instance using the getInstance() method. Next, we obtain the currency symbol with the getSymbol() method
Let’s verify that the Currency class returns the correct symbols for given currency codes. If an invalid code is provided, it should throw an exception:
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. Using Locale With Currency Class
Applications can utilize the Locale class in combination with the Currency class to retrieve localized currency symbols. This approach is beneficial for internationalized applications that dynamically adjust currency symbols based on the user’s locale:
public class CurrencyLocaleUtil {
public String getSymbolForLocale(Locale locale) {
Currency currency = Currency.getInstance(locale);
return currency.getSymbol();
}
}
The getSymbolForLocale()Â method retrieves the currency symbol based on the provided locale.
Let’s ensure that the system correctly retrieves the currency symbol based on 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. Using a Hardcoded Map
A predefined Map provides an easy and flexible way to control currency symbol mappings explicitly. This approach is particularly useful when applications need to display consistent symbols in the UI, handle less common currencies, or enforce specific formatting rules that are independent of locale settings. It works best in scenarios where the set of supported currencies is limited and unlikely to change frequently:
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");
}
}
The test below verifies that the hardcoded Map returns the correct symbol for known codes and defaults to “Unknown” for unrecognized ones:
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. Comparison
Each approach offers different characteristics. The table below compares the use cases and ease of maintenance for each approach:
| Approach |
Maintenance |
Use Case |
| Currency class |
No manual updates needed |
Best for standard applications with localization support |
| Hardcoded Map |
Requires manual updates |
Suitable when full control over currency symbols is required or when handling custom symbols |
| Locale |
No manual updates needed |
Best for internationalized applications |
If the application needs a fixed set of currency symbols, the hardcoded map approach is ideal. If we require localization support, we can consider the Currency class or a Locale-based solution.
4. Conclusion
Choosing the right approach depends on use case requirements. The Currency class is reliable, a hardcoded Map is optimal for a fixed set of symbols, and a Locale approach is ideal for applications needing regional adaptation.
We should choose an approach based on application requirements such as localization needs, consistency of symbols, and ease of maintenance.
The code backing this article is available on GitHub. Once you're
logged in as a Baeldung Pro Member, start learning and coding on the project.