Я нашел два способа получить объект BigDecimal из двойного d.
1. new BigDecimal(d)
2. BigDecimal.valueOf(d)
Что было бы лучше? Будет ли valueOf создавать новый объект?
В общем (не только BigDecimal) что рекомендуется - new или valueOf?
Спасибо.
Я нашел два способа получить объект BigDecimal из двойного d.
1. new BigDecimal(d)
2. BigDecimal.valueOf(d)
Что было бы лучше? Будет ли valueOf создавать новый объект?
В общем (не только BigDecimal) что рекомендуется - new или valueOf?
Спасибо.
Ответы:
Это два отдельных вопроса: «Для чего мне использовать BigDecimal?» и "Что мне вообще делать?"
For BigDecimal: это немного сложно, потому что они не делают то же самое . BigDecimal.valueOf(double)будет использовать каноническое Stringпредставление о doubleстоимости передаваемого в экземпляр BigDecimalобъекта. Другими словами: ценность BigDecimalобъекта будет тем, что вы видите, когда делаете System.out.println(d).
Однако, если вы используете new BigDecimal(d), то BigDecimalбудет пытаться представить doubleзначение как можно точнее . Это обычно приводит к хранению гораздо большего количества цифр, чем вы хотите. Строго говоря, это более правильно valueOf(), но намного менее интуитивно понятно.
В JavaDoc есть хорошее объяснение этого:
Результаты этого конструктора могут быть несколько непредсказуемыми. Можно предположить, что запись
new BigDecimal(0.1)на Java создает a,BigDecimalкоторый точно равен 0,1 (немасштабированное значение 1, со шкалой 1), но на самом деле он равен 0,1000000000000000055511151231257827021181583404541015625. Это связано с тем, что 0,1 не может быть представлено точно как adouble(или, если на то пошло, как двоичная дробь любой конечной длины). Таким образом, значение, передаваемое конструктору, не совсем равно 0,1, несмотря на внешний вид.
В общем, если результат такой же (то есть не в случае BigDecimal, а в большинстве других случаев), то valueOf()следует предпочесть: он может выполнять кэширование общих значений (как показано на Integer.valueOf()) и даже изменять поведение кеширования без необходимо изменить вызывающего абонента. всегдаnew будет создавать новое значение, даже если в этом нет необходимости (лучший пример: vs. ).new Boolean(true)Boolean.valueOf(true)
new BigDecimal()лучше BigDecimal.valueOf()?
new BigDecimal()будет предпочтительнее, и пример того, когда BigDecimal.valueOf()предпочтительнее?
new BigDecimal(1.0/30.0);и BigDecimal.valueOf(1.0/30.0). Посмотрите, какой результат на самом деле ближе к числовой дроби 1/30.
Если вы используете свои BigDecimalобъекты для хранения валютных ценностей, я настоятельно рекомендую НЕ в своих расчетах какие-либо двойные значения.
Как указано в другом ответе, существуют известные проблемы с точностью с двойными значениями, и они снова будут вас преследовать.
Как только вы справитесь с этим, ответ на ваш вопрос будет прост. Всегда используйте метод конструктора со значением String в качестве аргумента конструктора, так как valueOfдля String.
Если вам нужны доказательства, попробуйте следующее:
BigDecimal bd1 = new BigDecimal(0.01);
BigDecimal bd2 = new BigDecimal("0.01");
System.out.println("bd1 = " + bd1);
System.out.println("bd2 = " + bd2);
Вы получите следующий результат:
bd1 = 0.01000000000000000020816681711721685132943093776702880859375
bd2 = 0.01
См. Также этот связанный вопрос
В основном valueOf (double val) просто делает это:
return new BigDecimal(Double.toString(val));
Поэтому -> да, будет создан новый объект :).
В общем, я думаю, это зависит от вашего стиля кодирования. Я бы не стал смешивать valueOf и new, если оба результата имеют одинаковый результат.
valueOf()имеет более интуитивное поведение, а new BigDecimal(d)более правильное . Попробуйте оба варианта и увидите разницу.
new BigDecimal(1) != new BigDecimal(1)ноBigDecimal.valueOf(1) == BigDecimal.valueOf(1)
BigDecimalнеизменен следует относиться так же, как примитивные обертки ( Integer, Byte, ...) и Stringтрактуются: идентификатор объекта должен не имеет значения в код, только значение должно иметь значение.
valueOf() должно быть предпочтительнее. Но обратите внимание, что это не кеширует (и, вероятно, оно того не стоит). BigDecimal.valueOf(double)