Создание настраиваемого типа BigDecimal
В моем приложении все значения 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);
не выполняет эту работу, но я не могу найти способ сделать это, возможно ли это?
Ответы
Ответ 1
Вы можете создать CustomBigDecimal
, который простирается от BigDecimal
. Однако, поскольку BigDecimal
неизменен, вы никогда не наследуете состояние (например, масштаб и режим округления) от родительского класса.
Я бы пошел на класс утилиты, предложенный в другом ответе, или, может быть, в оболочку, которая делегирует каждую операцию фактическому экземпляру BigDecimal
. Недостатком этого подхода является то, что ваш новый CustomBigDecimal
не будет BigDecimal
, поэтому они не будут взаимозаменяемыми.
EDIT: недостатком этого подхода является то, что вы должны делегировать около 50 методов. Не конец света с хорошей IDE, но определенно не очень привлекательный...
Если вы все равно хотите сделать наследование CustomBigDecimal
с BigDecimal
, вам нужно будет использовать подход декоратора:
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
Вы можете просто создать для себя метод, который создает BigDecimal с нулем. Что-то вроде:
public static BigDecimal scaled(String val) {
BigDecimal x = new BigDecimal(val);
return x.setScale(2, RoundingMode.HALF_UP);
}
Поместите его в класс-помощник, например BigDecimalHelper, BigDecimalFactory или что-то еще.:)
EDIT: немного изменил его, чтобы вернуть результаты setScale, так как BigDecimal является неизменным. И для дальнейшего ответа на исходный вопрос: никакое то, что вы написали, невозможно, так как состояние объекта не изменяется с помощью setScale().
Ответ 3
Вы можете хранить экземпляр singleton MathContext, например, и использовать их в качестве аргумента для BigDecimal Constructor.
Обычно вы можете делать:
MathContext context = new MathContext(2, RoundingMode.HALF_UP);
BigDecimal number = new BigDecimal(val, context);
Итак, если у вас есть MathContext как singleton, вы можете сделать:
BigDecimal number = new BigDecimal(val, MathInstanceHolder.getMathContext());
Где MathInstanceHolder содержит экземпляр MathContext.
Ответ 4
Просто чтобы быть другим и использовать Java 8 - вы также можете пойти лямбда на проблему:
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")