我遇到了两种方法来从Double d中获取BigDecimal对象。
1. new BigDecimal(d)
2. BigDecimal.valueOf(d)
哪种方法更好?valueOf会创建一个新对象吗?
通常(不只是BigDecimal),建议使用什么-new或valueOf?
谢谢。
我遇到了两种方法来从Double d中获取BigDecimal对象。
1. new BigDecimal(d)
2. BigDecimal.valueOf(d)
哪种方法更好?valueOf会创建一个新对象吗?
通常(不只是BigDecimal),建议使用什么-new或valueOf?
谢谢。
Answers:
这是两个独立的问题:“我应该做什么用BigDecimal
?” 和“我通常会做什么?”
对于BigDecimal
:这有点棘手,因为他们做的不一样。BigDecimal.valueOf(double)
将使用规范String
表示的的double
在实例化传递的值BigDecimal
对象。换句话说:BigDecimal
对象的值将是您执行操作时看到的System.out.println(d)
。
new BigDecimal(d)
但是,如果您使用,则BigDecimal
将会尝试尽可能准确地表示该double
值。通常,这将导致存储的位数超出您的期望。严格来说,它比正确,但直观性却差很多。valueOf()
JavaDoc中对此有一个很好的解释:
该构造函数的结果可能无法预测。有人可能会假设
new BigDecimal(0.1)
用Java 编写的代码会创建一个aBigDecimal
,它等于0.1(未缩放的值1,小数位为1),但实际上等于0.1000000000000000055511151231257827021181583404541015625。这是因为0.1无法精确地表示为double
(或就此而言,表示为任何有限长度的二进制分数)。因此,尽管出现,但是传递给构造函数的值并不完全等于0.1。
通常,如果结果相同(即,在情况下不是BigDecimal
,但在大多数其他情况下),valueOf()
则应优先考虑:它可以缓存公用值(如上所示Integer.valueOf()
),甚至可以更改缓存行为而无需呼叫者必须更改。即使没有必要,new
也会始终实例化一个新值(最佳示例:new Boolean(true)
vs 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)
它不进行任何缓存(也可能不值得)。