Creating a custom BigDecimal type

China☆狼群 提交于 2019-12-23 06:55:41

问题


In my application, all BigDecimal numbers are scaled to have two decimal places.. In other words, everytime I create a new BigDecimal in my code, I need to use the method scale too:

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

So, to minimize the work, I wanted to create my custom BigDecimal type, something like:

public class CustomBigDecimal extends BigDecimal {

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

}

I know this.setScale(2, RoundingMode.HALF_UP); doesn't do the job, but I can't find the way to do it, is it possible?


回答1:


You could create a CustomBigDecimal that extends from BigDecimal. However, as BigDecimal is immutable, you would never inherit state (such as the scale and rounding mode) from the parent class.

I'd go for the utility class suggested in another answer, or maybe a wrapper that delegates every operation to an actual BigDecimal instance. The downside of this approach is that your brand new CustomBigDecimal wouldn't be a BigDecimal, so they wouldn't be interchangeable.

EDIT: a downside of this approach is that you have to delegate about 50 methods. Not the end of the world with a good IDE, but definitely not very appealing...

If, after all, you still want to make CustomBigDecimal inherit from BigDecimal, you'd need to use a decorator approach:

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

}



回答2:


You could simply create a method for yourself that creates a BigDecimal with zero. Something like:

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

Put it in a helper class, like BigDecimalHelper, BigDecimalFactory or whatever. :)

EDIT: Changed it slightly to return the results of setScale, since BigDecimal is immutable. And to further answer the original question: no what you've written is not possible since the state of the object is not changed with setScale().




回答3:


You can store a singleton instance of a MathContext, for instance, and use them as argument to BigDecimal Constructor.

Usually you could do:

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

So, if you have a MathContext as singleton, you can do:

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

Where MathInstanceHolder contains a MathContext instance.




回答4:


Just to be different and utilize Java 8 - you could also go lambda on the problem:

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")


来源:https://stackoverflow.com/questions/28969492/creating-a-custom-bigdecimal-type

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!