首页 > 编程技术 > JAVA > Java 9中新的货币API
2015
01-10

Java 9中新的货币API

JSR 354定义了一套新的Java货币API,计划会在Java 9中正式引入。本文中我们将来看一下它的参考实现:JavaMoney的当前进展。主要是通过一些代码来演示下新的API的用法 。

在开始之前,我想先用一段话来简短地总结一下规范定义的这套新的API的用意何在:

对许多应用而言货币价值都是一个关键的特性,但JDK对此却几乎没有任何支持。严格来讲,现有的java.util.Currency类只是代表了当前ISO
4217货币的一个数据结构,但并没有关联的值或者自定义货币。JDK对货币的运算及转换也没有内建的支持,更别说有一个能够代表货币值的标准类型了。

如果你用的是Maven的话,只需把下面的引用添加到工里面便能够体验下该参考实现的当前功能了:

规范中提到的类及接口都在javax.money.*包下面。

我们先从核心的两个接口CurrencyUnit与MonetaryAmount开始讲起。

CurrencyUnit及MonetaryAmount

CurrencyUnit代表的是货币。它有点类似于现在的java.util.Currency类,不同之处在于它支持自定义的实现。从规范的定义来看,java.util.Currency也是可以实现该接口的。CurrencyUnit的实例可以通过MonetaryCurrencies工厂来获取:

MontetaryAmount代表的是某种货币的具体金额。通常它都会与某个CurrencyUnit绑定。MontetaryAmount和CurrencyUnit一样,也是一个能支持多种实现的接口。CurrencyUnit与MontetaryAmount的实现必须是不可变,线程安全且可比较的。


Money与FastMoney是JavaMoney库中MonetaryAmount的两种实现。Money是默认实现,它使用BigDecimal来存储金额。FastMoney是可选的另一个实现,它用long类型来存储金额。根据文档来看,FastMoney上的操作要比Money的快10到15倍左右。然而,FastMoney的金额大小与精度都受限于long类型。

注意了,这里的Money和FastMoney都是具体的实现类(它们在org.javamoney.moneta.*包下面,而不是javax.money.*)。如果你不希望指定具体类型的话,可以通过MonetaryAmountFactory来生成一个MonetaryAmount的实例:

当且仅当实现类,货币单位,以及数值全部相等时才认为这两个MontetaryAmount实例是相等的。


MonetaryAmount内包含丰富的方法,可以用来获取具体的货币,金额,精度等等:


MonetaryAmount的使用

可以在MonetaryAmount上进行算术运算:

舍入操作是金额换算里面非常重要的一部分。MonetaryAmount可以使用舍入操作符来进行四舍五入:


这里12.3456美金就会按当前货币默认的舍入规则来进行换算。

在操作MonetaryAmount集合时,有许多实用的工具方法可以用来进行过滤,排序以及分组。这些方法还可以与Java 8的流API一起配套使用。

看一下下面这个集合:

我们可以根据CurrencyUnit来进行金额过滤:


我们还可以过滤出大于或小于某个阈值的金额:


排序也是类似的:


还有分组操作:


MonetaryFunctions还提供了归约函数,可以用来获取最大值,最小值,以及求和:

自定义的MonetaryAmount操作

MonetaryAmount还提供了一个非常友好的扩展点叫作MonetaryOperator。MonetaryOperator是一个函数式接口,它接收一个MonetaryAmount入参并返回一个新的MonetaryAmount对象。

标准的API特性都是通过MonetaryOperator的接口来实现的。比方说,前面看到的舍入操作就是以MonetaryOperator接口的形式来提供的。

汇率

货币兑换率可以通过ExchangeRateProvider来获取。JavaMoney自带了多个不同的ExchangeRateProvider的实现。其中最重要的两个是ECBCurrentRateProvider与 IMFRateProvider。

ECBCurrentRateProvider查询的是欧洲中央银行(European Central Bank,ECB)的数据而IMFRateProvider查询的是国际货币基金组织(International Monetary Fund,IMF)的汇率。

如果没有指定ExchangeRateProvider的话返回的就是CompoundRateProvider。CompoundRateProvider会将汇率转换请求委派给一个ExchangeRateProvider链并将第一个返回准确结果的提供商的数据返回。

货币转换

不同货币间的转换可以通过ExchangeRateProvider返回的CurrencyConversions来完成。

请注意CurrencyConversion也实现了MonetaryOperator接口。正如其它操作一样,它也能通过MonetaryAmount.with()方法来调用。

格式化及解析

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

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


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

总结

新的货币API这里已经介绍得差不多了。并且目前它的实现也已经相对稳定了(但还需要多补充些文档)。期待能在Java 9中看到这套新的接口!

上述示例可在Github中下载到。

最后编辑:
作者:金豆豆
这个作者貌似有点懒,什么都没有留下。
捐 赠如果您觉得这篇文章有用处,请支持作者!鼓励作者写出更好更多的文章!