BigDecimal - 使用new或valueOf

Man*_*ani 87 java bigdecimal

我遇到了两种方法从Big d中获取BigDecimal对象.

1. new BigDecimal(d)
2. BigDecimal.valueOf(d)
Run Code Online (Sandbox Code Playgroud)

哪种方法更好?valueOf会创建一个新对象吗?

一般情况下(不仅仅是BigDecimal),推荐什么 - new或valueOf?

谢谢.

Joa*_*uer 148

这是两个不同的问题:"我应该用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 编写创建的数字BigDecimal恰好等于0.1(未缩放值为1,等级为1),但它实际上等于0.1000000000000000055511151231257827021181583404541015625.这是因为0.1不能精确地表示为double(或者,就此而言,作为任何有限长度的二进制分数).因此,传递给构造函数的值并不完全等于0.1,尽管有外观.

一般来说,如果结果是相同的(即不是在BigDecimal大多数情况下,但在大多数情况下),那么valueOf()应该是首选:它可以缓存常见值(如上所示Integer.valueOf()),它甚至可以改变缓存行为呼叫者必须改变.new始终实例化一个新值,即使没有必要(最好的例子:new Boolean(true)vs Boolean.valueOf(true).).

  • @ryvantage:如果一个严格优于另一个,那么就不需要两者,我的答案会更短.他们不做同样的事情,所以你不能那样排名. (4认同)
  • @Joachim,不清楚。`new BigDecimal()` 比 `BigDecimal.valueOf()` 好吗? (3认同)
  • @JoachimSauer,好的抱歉我应该更具体.你是否介绍一个例子,说明何时首选`new BigDecimal()`以及何时首选`BigDecimal.valueOf()`的例子? (2认同)
  • @BrianKnoblauch:具有讽刺意味的是,“新”实际上与输入双精度更紧密地匹配,并且 toString 输出通过切断正确但不需要区分一个双精度值和下一个双精度值的数字来“作弊”。 (2认同)

Dun*_*ear 44

如果您使用的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);
Run Code Online (Sandbox Code Playgroud)

您将获得以下输出:

bd1 = 0.01000000000000000020816681711721685132943093776702880859375
bd2 = 0.01
Run Code Online (Sandbox Code Playgroud)

另请参阅此相关问题


DXT*_*R66 6

基本上 valueOf(double val) 就是这样做的:

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

因此 -> 是的,将创建一个新对象:)。

一般来说,我认为这取决于您的编码风格。如果两者的结果相同,我不会混合 valueOf 和“new”。

  • 从技术上讲,**但是**:它会产生**巨大的**差异。`valueOf()` 具有更*直观* 的行为,而 `new BigDecimal(d)` 具有更*正确* 的行为。两者都试一下,看看有什么不同。 (7认同)
  • @user:是的,这就是为什么我说`valueOf()` 应该*通常* 是首选。但请注意,`BigDecimal.valueOf(double)` 不做任何缓存(而且它可能也不值得)。 (3认同)
  • @用户:是的,但是由于“BigDecimal”是不可变的,因此应该以与原始包装器(“Integer”,“Byte”,...)和“String”相同的方式对待它:对象标识*应该不重要*对于您的代码来说,只有*值*才重要。 (2认同)