Подтвердить что ты не робот

BigDecimal - использовать new или valueOf

Я столкнулся с двумя способами получения объекта BigDecimal из двойного d.

1. new BigDecimal(d)
2. BigDecimal.valueOf(d)

Какой будет лучший подход? Будет ли valueOf создавать новый объект?

В общем (не только BigDecimal), что рекомендуется - new или valueOf?

Спасибо.

4b9b3361

Ответ 1

Это два отдельных вопроса: "Что я должен использовать для BigDecimal?" и "Что я вообще делаю?"

Для BigDecimal: это немного сложно, потому что они не делают то же самое. BigDecimal.valueOf(double) будет использовать представление canonical String значение double, переданное для создания объекта BigDecimal. Другими словами: значение объекта BigDecimal будет тем, что вы видите, когда выполняете System.out.println(d).

Если вы используете new BigDecimal(d), то BigDecimal попытается представить значение double как можно точнее. Как правило, это приводит к тому, что гораздо больше цифр хранится, чем вы хотите. Строго говоря, это более корректно, чем valueOf(), но это намного менее интуитивно понятное.

В JavaDoc есть приятное объяснение:

Результаты этого конструктора могут быть несколько непредсказуемыми. Можно предположить, что запись new BigDecimal(0.1) в Java создает значение BigDecimal, которое в точности равно 0,1 (немасштабированное значение 1 со шкалой 1), но оно фактически равно 0,1000000000000000055511151231257827021181583404541015625. Это связано с тем, что 0,1 не может быть представлено точно как double (или, если на то пошло, как двоичная дробь любой конечной длины). Таким образом, значение, которое передается конструктору, не точно равно 0,1, независимо от того, что происходит.

В общем случае, если результат тот же (т.е. не в случае BigDecimal, но в большинстве других случаев), то предпочтительнее valueOf(): он может выполнять кэширование общих значений (как видно на Integer.valueOf()), и он даже может изменить поведение кэширования без необходимости изменения вызывающего. new всегда будет создавать новое значение, даже если это не необходимо (лучший пример: new Boolean(true) vs. Boolean.valueOf(true)).

Ответ 2

Если вы используете объекты BigDecimal для хранения значений валюты, я настоятельно рекомендую вам НЕ использовать любые двойные значения в любом месте их вычислений.

Как указано в другом ответе, существуют известные проблемы с двойными значениями, и они вернутся, чтобы преследовать вас в свое время.

Как только вы пройдете мимо, ответ на ваш вопрос прост. Всегда используйте метод конструктора со значением String как аргумент конструктора, так как для String нет метода valueOf.

Если вам нужны доказательства, попробуйте следующее:

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

Смотрите также этот связанный вопрос

Ответ 3

В основном valueOf (double val) просто делает это:

return new BigDecimal(Double.toString(val));

Поэтому → yep, будет создан новый объект:).

В целом, я думаю, это зависит от вашего стиля кодирования. Я бы не смешал valueOf и "новый", если оба они имеют одинаковый результат.