Java 金额封装bean

package org.near.toolkit.model;


import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Currency;

/**
 * 单币种货币类,处理货币算术、币种和取整。
 *
 * <p>
 * 货币类中封装了货币金额和币种。目前金额在内部是long类型表示,
 * 单位是所属币种的最小货币单位(对人民币是分)。
 *
 * <p>
 * 目前,货币实现了以下主要功能:<br>
 * <ul>
 *   <li>支持货币对象与double(float)/long(int)/String/BigDecimal之间相互转换。
 *   <li>货币类在运算中提供与JDK中的BigDecimal类似的运算接口,
 *       BigDecimal的运算接口支持任意指定精度的运算功能,能够支持各种
 *       可能的财务规则。
 *   <li>货币类在运算中也提供一组简单运算接口,使用这组运算接口,则在
 *       精度处理上使用缺省的处理规则。
 *   <li>推荐使用Money,不建议直接使用BigDecimal的原因之一在于,
 *       使用BigDecimal,同样金额和币种的货币使用BigDecimal存在多种可能
 *       的表示,例如:new BigDecimal("10.5")与new BigDecimal("10.50")
 *       不相等,因为scale不等。使得Money类,同样金额和币种的货币只有
 *       一种表示方式,new Money("10.5")和new Money("10.50")应该是相等的。
 *   <li>不推荐直接使用BigDecimal的另一原因在于, BigDecimal是Immutable,
 *       一旦创建就不可更改,对BigDecimal进行任意运算都会生成一个新的
 *       BigDecimal对象,因此对于大批量统计的性能不够满意。Money类是
 *       mutable的,对大批量统计提供较好的支持。
 *   <li>提供基本的格式化功能。
 *   <li>Money类中不包含与业务相关的统计功能和格式化功能。业务相关的功能
 *       建议使用utility类来实现。
 *   <li>Money类实现了Serializable接口,支持作为远程调用的参数和返回值。
 *   <li>Money类实现了equals和hashCode方法。
 * </ul>
 *
 */
public class Money implements Serializable, Comparable {

    /**
     * Comment for <code>serialVersionUID</code>
     */
    private static final long  serialVersionUID      = 6009335074727417445L;

    /**
     * 缺省的币种代码,为CNY(人民币)。
     */
    public static final String DEFAULT_CURRENCY_CODE = "CNY";

    /**
     * 缺省的取整模式,为<code>BigDecimal.ROUND_HALF_EVEN
     * (四舍五入,当小数为0.5时,则取最近的偶数)。
     */
    public static final int    DEFAULT_ROUNDING_MODE = BigDecimal.ROUND_HALF_EVEN;

    /**
     * 一组可能的元/分换算比例。
     *
     * <p>
     * 此处,“分”是指货币的最小单位,“元”是货币的最常用单位,
     * 不同的币种有不同的元/分换算比例,如人民币是100,而日元为1。
     */
    private static final int[] centFactors           = new int[] { 1, 10, 100, 1000 };

    /**
     * 金额,以分为单位。
     */
    private long               cent;

    /**
     * 币种。
     */
    private Currency           currency;

    // 构造器 ====================================================

    /**
     * 缺省构造器。
     *
     * <p>
     * 创建一个具有缺省金额(0)和缺省币种的货币对象。
     */
    public Money() {
        this(0);
    }

    /**
     * 构造器。
     *
     * <p>
     * 创建一个具有金额<code>yuan</code>元<code>cent</cent>分和缺省币种的货币对象。
     *
     * @param yuan 金额元数。
     * @param cent 金额分数。
     */
    public Money(long yuan, int cent) {
        this(yuan, cent, Currency.getInstance(DEFAULT_CURRENCY_CODE));
    }

    /**
     * 构造器。
     *
     * <p>
     * 创建一个具有金额<code>yuan</code>元<code>cent</code>分和指定币种的货币对象。
     *
     * @param yuan 金额元数。
     * @param cent 金额分数。
     */
    public Money(long yuan, int cent, Currency currency) {
        this.currency = currency;

        this.cent = (yuan * getCentFactor()) + (cent % getCentFactor());
    }

    /**
     * 构造器。
     *
     * <p>
     * 创建一个具有金额<code>amount</code>元和缺省币种的货币对象。
     *
     * @param amount 金额,以元为单位。
     */
    public Money(String amount) {
        this(amount, Currency.getInstance(DEFAULT_CURRENCY_CODE));
    }

    /**
     * 构造器。
     *
     * <p>
     * 创建一个具有金额<code>amount</code>元和指定币种<code>currency</code>的货币对象。
     *
     * @param amount 金额,以元为单位。
     * @param currency 币种。
     */
    public Money(String amount, Currency currency) {
        this(new BigDecimal(amount), currency);
    }

    /**
     * 构造器。
     *
     * <p>
     * 创建一个具有金额<code>amount</code>元和指定币种<code>currency</code>的货币对象。
     * 如果金额不能转换为整数分,则使用指定的取整模式<code>roundingMode</code>取整。
     *
     * @param amount 金额,以元为单位。
     * @param currency 币种。
     * @param roundingMode 取整模式。
     */
    public Money(String amount, Currency currency, int roundingMode) {
        this(new BigDecimal(amount), currency, roundingMode);
    }

    /**
     * 构造器。
     *
     * <p>
     * 创建一个具有参数<code>amount</code>指定金额和缺省币种的货币对象。
     * 如果金额不能转换为整数分,则使用四舍五入方式取整。
     *
     * <p>
     * 注意:由于double类型运算中存在误差,使用四舍五入方式取整的
     * 结果并不确定,因此,应尽量避免使用double类型创建货币类型。
     * 例:
     * <code>
     * assertEquals(999, Math.round(9.995 * 100));
     * assertEquals(1000, Math.round(999.5));
     * money = new Money((9.995));
     * assertEquals(999, money.getCent());
     * money = new
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值