创建自定义 BigDecimal 类型

Creating a custom BigDecimal type

在我的应用程序中,所有 BigDecimal 数字都被缩放为有两位小数。换句话说,每次我在代码中创建一个新的 BigDecimal 时,我也需要使用方法缩放:

BigDecimal x = BigDecimal.ZERO;
x.setScale(2, RoundingMode.HALF_UP);

因此,为了尽量减少工作量,我想创建自定义 BigDecimal 类型,例如:

public class CustomBigDecimal extends BigDecimal {

    public CustomBigDecimal(String val) {
        super(val);
        this.setScale(2, RoundingMode.HALF_UP);
    }

}

我知道 this.setScale(2, RoundingMode.HALF_UP); 做不到,但我找不到方法,可以吗?

您可以简单地为自己创建一个方法来创建一个零的 BigDecimal。类似于:

public static BigDecimal scaled(String val) {
    BigDecimal x = new BigDecimal(val);
    return x.setScale(2, RoundingMode.HALF_UP);
}

将它放在帮助程序 class 中,例如 BigDecimalHelper、BigDecimalFactory 或其他。 :)

编辑:将其稍微更改为 return setScale 的结果,因为 BigDecimal 是不可变的。并进一步回答最初的问题:不,你写的是不可能的,因为对象的状态没有用 setScale() 改变。

例如,您可以存储 MathContext 的单例实例,并将它们用作 BigDecimal 构造函数的参数。

通常你可以这样做:

MathContext context = new MathContext(2, RoundingMode.HALF_UP);
BigDecimal number = new BigDecimal(val, context);

所以,如果你有一个 MathContext 作为单例,你可以这样做:

BigDecimal number = new BigDecimal(val, MathInstanceHolder.getMathContext());

其中 MathInstanceHolder 包含一个 MathContext 实例。

您可以创建一个从 BigDecimal 扩展的 CustomBigDecimal。但是,由于 BigDecimal 是不可变的,您永远不会从父级 class.

继承状态(例如缩放和舍入模式)

我会选择另一个答案中建议的实用程序 class,或者可能是将每个操作委托给实际 BigDecimal 实例的包装器。这种方法的缺点是您的全新 CustomBigDecimal 不会是 BigDecimal,因此它们不能互换。

编辑:这种方法的缺点是您必须委托大约 50 个方法。不是世界末日的好IDE,但绝对不是很吸引人...

如果你仍然想让 CustomBigDecimal 继承自 BigDecimal,你需要使用 decorator 方法:

public class CustomBigDecimal extends BigDecimal {

    private final BigDecimal value;

    private CustomBigDecimal(BigDecimal value) {
        super(value.toPlainString()); // needed to compile, 
                                      // useless except for implicit null-check
        this.value = value;
    }

    public CustomBigDecimal(String val) {
        this(new BigDecimal(val).setScale(2, RoundingMode.HALF_UP));
    }

    @Override
    public CustomBigDecimal abs() {
        return new CustomBigDecimal(this.value.abs());
    }

    // TODO all other methods

}

只是为了与众不同并利用 Java 8 - 你也可以在问题上使用 lambda:

public static Function<String, BigDecimal> SCALED_BIG_DECIMAL = (val) -> new BigDecimal(val).setScale(2, RoundingMode.HALF_UP);
...

// and this is how you would use it
SCALED_BIG_DECIMAL.apply("20.2343425")