Ответ 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)
).