(только что нашел соответствующую проблему на GitHub ?)
Вероятно, это связано с предположением, связанным с реализацией, что экземпляры RoundedMoney
всегда будут содержать округленные значения, но, очевидно, это не применяется в фабричных методах и конструкторах этого класса. Вы можете счастливо построить его с необоснованными ценностями.
При выполнении математических операций с этим классом применяется некоторая арифметическая оптимизация: в примерах A1 и C1 используются элементы идентичности сложения и умножения в правой части, следовательно, они фактически являются no-ops, и будет возвращено this
, представляющее начальное необоснованное значение. Примеры A2 и C2 теоретически могут напрямую возвращать правый оператор, но эта оптимизация отсутствует, поэтому RoundedMoney
фактически начинает вычислять (и округлять) результат.
Пример B1 просто переворачивает знак числового значения. Здесь применяются те же допущения: если x
является правильно округленным значением, то -x
также правильно округляется [1] . Таким образом, RoundedMoney
не потрудится применить округление к новому числовому значению. Напротив, пример B2 не оптимизирован, а рассчитан и округлен.
Итак, я думаю, что фактические виновники фабричные методы , которые не будут применять округление к предоставленным пользователем значениям:
public static RoundedMoney of(BigDecimal number, CurrencyUnit currency) {
return new RoundedMoney(number, currency, Monetary.getDefaultRounding());
}
public static RoundedMoney of(BigDecimal number, CurrencyUnit currency, MonetaryOperator rounding) {
return new RoundedMoney(number, currency, rounding);
}
скорее всего должно быть
public static RoundedMoney of(BigDecimal number, CurrencyUnit currency) {
return of(number, currency, Monetary.getDefaultRounding());
}
public static RoundedMoney of(BigDecimal number, CurrencyUnit currency, MonetaryOperator rounding) {
return new RoundedMoney(number, currency, rounding).with(rounding);
}
Я бы поспорил, что это ошибка, но так как нет большой (нет?) Документации о том, как этот класс предполагается использовать - или вообще не использовать - это может быть даже предполагаемое поведение?
[1]: Это интересно. Есть ли округления, которые не удовлетворят этому предположению? Фактически, поскольку RoundedMoney
использует MoentaryOperator
для применения округления, можно легко передать некоторый произвольный "несимметричный" оператор.