Java java지도 시간 Java 9의 새로운 통화 API

Java 9의 새로운 통화 API

Nov 26, 2016 am 10:10 AM
api java

JSR 354는 Java 9에서 공식적으로 도입될 예정인 새로운 Java 통화 API를 정의합니다. 이 기사에서는 참조 구현인 JavaMoney의 현재 진행 상황을 살펴보겠습니다.

Java 8의 새로운 날짜 및 시간 API에 대한 이전 기사와 마찬가지로 이 기사에서는 주로 일부 코드를 통해 새로운 API의 사용법을 보여줍니다.

시작하기 전에 사양에 정의된 이 새로운 API 세트의 목적을 한 단락으로 간략하게 요약하고 싶습니다.

많은 애플리케이션에서 금전적 가치가 핵심입니다. 그러나 JDK는 이를 거의 지원하지 않습니다. 엄밀히 말하면 기존 java.util.Currency 클래스는 현재 ISO 4217 통화의 데이터 구조만 나타낼 뿐 관련 값이나 사용자 정의 통화는 없습니다. JDK에는 통화 값을 나타낼 수 있는 표준 유형은 물론 통화 연산 및 변환에 대한 기본 지원도 없습니다.

Maven을 사용하는 경우 참조 구현의 현재 기능을 경험하려면 프로젝트에 다음 참조만 추가하면 됩니다.

<dependency>
  <groupId>org.javamoney</groupId>
  <artifactId>moneta</artifactId>
  <version>0.9</version>
</dependency>
로그인 후 복사

사양에 언급된 클래스와 인터페이스는 다음과 같습니다. javax.money.* 패키지 아래에 있습니다.

두 가지 핵심 인터페이스인 MoneyUnit과 MonetaryAmount부터 시작해 보겠습니다.

CurrencyUnit 및 MonetaryAmount

CurrencyUnit은 통화를 나타냅니다. 이는 사용자 정의 구현을 지원한다는 점을 제외하면 현재 java.util.Currency 클래스와 다소 유사합니다. 표준 정의에서 java.util.Currency도 이 인터페이스를 구현할 수 있습니다. MoneyUnit의 인스턴스는 MonetaryCurrities 팩토리를 통해 얻을 수 있습니다.

// 根据货币代码来获取货币单位 CurrencyUnit euro = MonetaryCurrencies.getCurrency("EUR");
    CurrencyUnit usDollar = MonetaryCurrencies.getCurrency("USD"); // 根据国家及地区来获取货币单位
    CurrencyUnit yen = MonetaryCurrencies.getCurrency(Locale.JAPAN); CurrencyUnit
    canadianDollar = MonetaryCurrencies.getCurrency(Locale.CANADA);
로그인 후 복사

MontetaryAmount는 특정 통화의 특정 금액을 나타냅니다. 일반적으로 이는 MoneyUnit에 바인딩됩니다.

CurrencyUnit과 마찬가지로 MontetaryAmount도 여러 구현을 지원할 수 있는 인터페이스입니다.

CurrencyUnit 및 MontetaryAmount의 구현은 변경이 불가능하고 스레드로부터 안전하며 비교 가능해야 합니다.

/ get MonetaryAmount from CurrencyUnit
CurrencyUnit euro = MonetaryCurrencies.getCurrency("EUR");
MonetaryAmount fiveEuro = Money.of(5, euro);
  
// get MonetaryAmount from currency code
MonetaryAmount tenUsDollar = Money.of(10, "USD");
  
// FastMoney is an alternative MonetaryAmount factory that focuses on performance
MonetaryAmount sevenEuro = FastMoney.of(7, euro);
로그인 후 복사

Money와 FastMoney는 JavaMoney 라이브러리에서 MonetaryAmount를 구현한 두 가지입니다. Money는 BigDecimal을 사용하여 금액을 저장하는 기본 구현입니다. FastMoney는 긴 유형을 사용하여 금액을 저장하는 선택적 구현입니다. 문서에 따르면 FastMoney의 작업은 Money의 작업보다 약 10~15배 빠릅니다. 그러나 FastMoney의 금액 크기와 정밀도는 Long 유형으로 제한됩니다.

여기서 Money 및 FastMoney는 특정 구현 클래스입니다(javax.money.*가 아닌 org.javamoney.moneta.* 패키지에 있음). 특정 유형을 지정하지 않으려는 경우 MonetaryAmountFactory를 사용하여 MonetaryAmount 인스턴스를 생성할 수 있습니다.

MonetaryAmount specAmount = MonetaryAmounts.getDefaultAmountFactory()
                .setNumber(123.45) .setCurrency("USD") .create();
로그인 후 복사

이러한 두 MontetaryAmount 인스턴스는 구현 클래스인 통화가 동일한 경우에만 동일한 것으로 간주됩니다. 단위와 가치는 모두 동일합니다.

MonetaryAmount oneEuro = Money.of(1, MonetaryCurrencies.getCurrency("EUR"));
boolean isEqual = oneEuro.equals(Money.of(1, "EUR")); // true
boolean isEqualFast = oneEuro.equals(FastMoney.of(1, "EUR")); // false
로그인 후 복사

MonetaryAmount에는 특정 통화, 금액, 정밀도 등을 얻는 데 사용할 수 있는 다양한 방법이 포함되어 있습니다.

MonetaryAmount monetaryAmount = Money.of(123.45, euro);
CurrencyUnit currency = monetaryAmount.getCurrency();
NumberValue numberValue = monetaryAmount.getNumber();
  
int intValue = numberValue.intValue(); // 123
double doubleValue = numberValue.doubleValue(); // 123.45
long fractionDenominator = numberValue.getAmountFractionDenominator(); // 100
long fractionNumerator = numberValue.getAmountFractionNumerator(); // 45
int precision = numberValue.getPrecision(); // 5
  
// NumberValue extends java.lang.Number.
// So we assign numberValue to a variable of type Number
Number number = numberValue;
로그인 후 복사

MonetaryAmount 사용

는 MonetaryAmount의 산술 연산에서 찾을 수 있습니다:

MonetaryAmount twelveEuro = fiveEuro.add(sevenEuro); // "EUR 12"
MonetaryAmount twoEuro = sevenEuro.subtract(fiveEuro); // "EUR 2"
MonetaryAmount sevenPointFiveEuro = fiveEuro.multiply(1.5); // "EUR 7.5"
  
// MonetaryAmount can have a negative NumberValue
MonetaryAmount minusTwoEuro = fiveEuro.subtract(sevenEuro); // "EUR -2"
  
// some useful utility methods
boolean greaterThan = sevenEuro.isGreaterThan(fiveEuro); // true
boolean positive = sevenEuro.isPositive(); // true
boolean zero = sevenEuro.isZero(); // false
  
// Note that MonetaryAmounts need to have the same CurrencyUnit to do mathematical operations
// this fails with: javax.money.MonetaryException: Currency mismatch: EUR/USD
fiveEuro.add(tenUsDollar);
로그인 후 복사

반올림 연산은 금액 변환에서 매우 중요한 부분입니다. MonetaryAmount는 반올림 연산자를 사용하여 반올림할 수 있습니다.

CurrencyUnit usd = MonetaryCurrencies.getCurrency("USD");
MonetaryAmount dollars = Money.of(12.34567, usd);
MonetaryOperator roundingOperator = MonetaryRoundings.getRounding(usd);
MonetaryAmount roundedDollars = dollars.with(roundingOperator); // USD 12.35
로그인 후 복사

여기서 12.3456 미국 달러는 현재 통화의 기본 반올림 규칙에 따라 변환됩니다.

MonetaryAmount 컬렉션을 운영할 때 필터링, 정렬, 그룹화에 사용할 수 있는 실용적인 도구와 방법이 많이 있습니다. 이러한 메서드는 Java 8의 스트림 API와 함께 사용할 수도 있습니다.

다음 컬렉션을 살펴보세요.

List<MonetaryAmount> amounts = new ArrayList<>();
amounts.add(Money.of(2, "EUR"));
amounts.add(Money.of(42, "USD"));
amounts.add(Money.of(7, "USD"));
amounts.add(Money.of(13.37, "JPY"));
amounts.add(Money.of(18, "USD"));
로그인 후 복사

CurrencyUnit을 기준으로 금액을 필터링할 수 있습니다.

CurrencyUnit yen = MonetaryCurrencies.getCurrency("JPY");
CurrencyUnit dollar = MonetaryCurrencies.getCurrency("USD");
// 根据货币过滤,只返回美金
// result is [USD 18, USD 7, USD 42]
List<MonetaryAmount> onlyDollar = amounts.stream()
    .filter(MonetaryFunctions.isCurrency(dollar))
    .collect(Collectors.toList());
  
// 根据货币过滤,只返回美金和日元
// [USD 18, USD 7, JPY 13.37, USD 42]
List<MonetaryAmount> onlyDollarAndYen = amounts.stream()
    .filter(MonetaryFunctions.isCurrency(dollar, yen))
    .collect(Collectors.toList());
로그인 후 복사

더 큰 금액을 필터링할 수도 있습니다. 특정 임계값 이하 금액:

MonetaryAmount tenDollar = Money.of(10, dollar);
  
// [USD 42, USD 18]
List<MonetaryAmount> greaterThanTenDollar = amounts.stream()
    .filter(MonetaryFunctions.isCurrency(dollar))
    .filter(MonetaryFunctions.isGreaterThan(tenDollar))
    .collect(Collectors.toList());
로그인 후 복사

정렬도 유사합니다:

// Sorting dollar values by number value
// [USD 7, USD 18, USD 42]
List<MonetaryAmount> sortedByAmount = onlyDollar.stream()
    .sorted(MonetaryFunctions.sortNumber())
    .collect(Collectors.toList());
  
// Sorting by CurrencyUnit
// [EUR 2, JPY 13.37, USD 42, USD 7, USD 18]
List<MonetaryAmount> sortedByCurrencyUnit = amounts.stream()
    .sorted(MonetaryFunctions.sortCurrencyUnit())
    .collect(Collectors.toList());
로그인 후 복사

그룹화 작업도 있습니다:

// 按货币单位进行分组
// {USD=[USD 42, USD 7, USD 18], EUR=[EUR 2], JPY=[JPY 13.37]}
Map<CurrencyUnit, List<MonetaryAmount>> groupedByCurrency = amounts.stream()
    .collect(MonetaryFunctions.groupByCurrencyUnit());
  
// 分组并进行汇总
Map<CurrencyUnit, MonetarySummaryStatistics> summary = amounts.stream()
    .collect(MonetaryFunctions.groupBySummarizingMonetary()).get();
  
// get summary for CurrencyUnit USD
MonetarySummaryStatistics dollarSummary = summary.get(dollar);
MonetaryAmount average = dollarSummary.getAverage(); // "USD 22.333333333333333333.."
MonetaryAmount min = dollarSummary.getMin(); // "USD 7"
MonetaryAmount max = dollarSummary.getMax(); // "USD 42"
MonetaryAmount sum = dollarSummary.getSum(); // "USD 67"
long count = dollarSummary.getCount(); // 3
로그인 후 복사

MonetaryFunctions 최대값, 최소값 및 합계를 구하는 데 사용할 수 있는 축소 기능도 제공합니다.

List<MonetaryAmount> amounts = new ArrayList<>();
amounts.add(Money.of(10, "EUR"));
amounts.add(Money.of(7.5, "EUR"));
amounts.add(Money.of(12, "EUR"));
  
Optional<MonetaryAmount> max = amounts.stream().reduce(MonetaryFunctions.max()); // "EUR 7.5"
Optional<MonetaryAmount> min = amounts.stream().reduce(MonetaryFunctions.min()); // "EUR 12"
Optional<MonetaryAmount> sum = amounts.stream().reduce(MonetaryFunctions.sum()); //
로그인 후 복사

사용자 정의된 MonetaryAmount 작업

MonetaryAmount는 MonetaryOperator라는 매우 친숙한 확장 지점도 제공합니다. . MonetaryOperator는 MonetaryAmount 입력 매개변수를 수신하고 새 MonetaryAmount 개체를 반환하는 기능적 인터페이스입니다.

// A monetary operator that returns 10% of the input MonetaryAmount
// Implemented using Java 8 Lambdas
MonetaryOperator tenPercentOperator = (MonetaryAmount amount) -> {
  BigDecimal baseAmount = amount.getNumber().numberValue(BigDecimal.class);
  BigDecimal tenPercent = baseAmount.multiply(new BigDecimal("0.1"));
  return Money.of(tenPercent, amount.getCurrency());
};
  
MonetaryAmount dollars = Money.of(12.34567, "USD");
  
// apply tenPercentOperator to MonetaryAmount
MonetaryAmount tenPercentDollars = dollars.with(tenPercentOperator); // USD 1.234567
로그인 후 복사

표준 API 기능은 MonetaryOperator 인터페이스를 통해 구현됩니다. 예를 들어 앞서 본 반올림 연산은 MonetaryOperator 인터페이스 형태로 제공됩니다.

환율

환율은 ExchangeRateProvider를 통해 확인할 수 있습니다. JavaMoney에는 다양한 ExchangeRateProvider 구현이 함께 제공됩니다. 가장 중요한 두 가지는 ECBCurrentRateProvider와 IMFRateProvider입니다.

ECBCurrentRateProvider는 유럽중앙은행(ECB)의 데이터를 쿼리하고 IFRateProvider는 국제통화기금(IMF)의 환율을 쿼리합니다.

// get the default ExchangeRateProvider (CompoundRateProvider)
ExchangeRateProvider exchangeRateProvider = MonetaryConversions.getExchangeRateProvider();
  
// get the names of the default provider chain
// [IDENT, ECB, IMF, ECB-HIST]
List<String> defaultProviderChain = MonetaryConversions.getDefaultProviderChain();
  
// get a specific ExchangeRateProvider (here ECB)
ExchangeRateProvider ecbExchangeRateProvider = MonetaryConversions.getExchangeRateProvider("ECB");
로그인 후 복사

ExchangeRateProvider를 지정하지 않으면CompoundRateProvider가 반환됩니다. CompoundRateProvider는 환율 변환 요청을 ExchangeRateProvider 체인에 위임하고 정확한 결과를 반환하는 첫 번째 공급자로부터 데이터를 반환합니다.

// get the exchange rate from euro to us dollar
ExchangeRate rate = exchangeRateProvider.getExchangeRate("EUR", "USD");
  
NumberValue factor = rate.getFactor(); // 1.2537 (at time writing)
CurrencyUnit baseCurrency = rate.getBaseCurrency(); // EUR
CurrencyUnit targetCurrency = rate.getCurrency(); // USD
로그인 후 복사

통화 변환

ExchangeRateProvider에서 반환한 CurrentConversions를 통해 서로 다른 통화 간의 변환을 완료할 수 있습니다.

// get the CurrencyConversion from the default provider chain
CurrencyConversion dollarConversion = MonetaryConversions.getConversion("USD");
  
// get the CurrencyConversion from a specific provider
CurrencyConversion ecbDollarConversion = ecbExchangeRateProvider.getCurrencyConversion("USD");
  
MonetaryAmount tenEuro = Money.of(10, "EUR");
  
// convert 10 euro to us dollar
MonetaryAmount inDollar = tenEuro.with(dollarConversion); // "USD 12.537" (at the time writing)
로그인 후 복사

CurrencyConversion은 MonetaryOperator 인터페이스도 구현한다는 점에 유의하세요. 다른 작업과 마찬가지로 MonetaryAmount.with() 메서드를 통해 호출할 수도 있습니다.

형식 지정 및 구문 분석

  MonetaryAmount可以通过MonetaryAmountFormat来与字符串进行解析/格式化。

// formatting by locale specific formats
MonetaryAmountFormat germanFormat = MonetaryFormats.getAmountFormat(Locale.GERMANY);
MonetaryAmountFormat usFormat = MonetaryFormats.getAmountFormat(Locale.CANADA);
  
MonetaryAmount amount = Money.of(12345.67, "USD");
  
String usFormatted = usFormat.format(amount); // "USD12,345.67"
String germanFormatted = germanFormat.format(amount); // 12.345,67 USD
  
// A MonetaryAmountFormat can also be used to parse MonetaryAmounts from strings
MonetaryAmount parsed = germanFormat.parse("12,4 USD");
로그인 후 복사

可以通过AmountFormatQueryBuilder来生成自定义的格式。

// Creating a custom MonetaryAmountFormat
MonetaryAmountFormat customFormat = MonetaryFormats.getAmountFormat(
    AmountFormatQueryBuilder.of(Locale.US)
        .set(CurrencyStyle.NAME)
        .set("pattern", "00,00,00,00.00 ¤")
        .build());
  
// results in "00,01,23,45.67 US Dollar"
String formatted = customFormat.format(amount);
로그인 후 복사

注意,这里的¤符号在模式串中是作为货币的占位符。

본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.

뜨거운 기사 태그

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)

자바의 제곱근 자바의 제곱근 Aug 30, 2024 pm 04:26 PM

자바의 제곱근

자바의 완전수 자바의 완전수 Aug 30, 2024 pm 04:28 PM

자바의 완전수

Java의 난수 생성기 Java의 난수 생성기 Aug 30, 2024 pm 04:27 PM

Java의 난수 생성기

자바의 암스트롱 번호 자바의 암스트롱 번호 Aug 30, 2024 pm 04:26 PM

자바의 암스트롱 번호

자바의 웨카 자바의 웨카 Aug 30, 2024 pm 04:28 PM

자바의 웨카

Java의 스미스 번호 Java의 스미스 번호 Aug 30, 2024 pm 04:28 PM

Java의 스미스 번호

Java Spring 인터뷰 질문 Java Spring 인터뷰 질문 Aug 30, 2024 pm 04:29 PM

Java Spring 인터뷰 질문

Java 8 Stream foreach에서 나누거나 돌아 오시겠습니까? Java 8 Stream foreach에서 나누거나 돌아 오시겠습니까? Feb 07, 2025 pm 12:09 PM

Java 8 Stream foreach에서 나누거나 돌아 오시겠습니까?

See all articles