1. Overview
1.概述
When we work with BigDecimal, representing the numerical value zero using BigDecimal is a common task. However, we’re often faced with a choice between two similar approaches: using BigDecimal.ZERO or creating a new BigDecimal object with the constructor new BigDecimal(0).
当我们使用 BigDecimal 时, 使用 BigDecimal 表示数值 zero 是一项常见的任务。然而,我们经常面临在两种类似方法中做出选择:使用 BigDecimal.ZERO 或使用构造函数 new BigDecimal(0) 创建一个新的 BigDecimal 对象。
In this tutorial, we’ll explore the subtle yet significant distinctions between these two methods and discuss when to choose one over the other.
在本教程中,我们将探讨这两种方法之间微妙而重要的区别,并讨论何时选择其中一种方法。
Also, for simplicity, we’ll use unit test assertions to verify results.
此外,为了简单起见,我们将使用单元测试断言来验证结果。
2. Comparing BigDecimal Objects
2.比较 BigDecimal 对象
Before we compare BigDecimal.ZERO and new BigDecimal(0), let’s quickly see how to compare two BigDecimal objects.
在比较 BigDecimal.ZERO 和 new BigDecimal(0) 之前,让我们快速了解如何比较两个 BigDecimal 对象。
Given that the BigDecimal class implements the Comparable interface, it provides us with the flexibility to compare two BigDecimals using either the equals() method or the compareTo() method. However, it’s crucial to recognize that these two methods conduct distinct comparisons between two BigDecimal instances.
鉴于 BigDecimal 类实现了 Comparable 接口,它为我们提供了使用 equals() 方法或 compareTo() 方法比较两个 BigDecimal 的灵活性。但是,我们必须认识到,这两种方法在两个 BigDecimal 实例之间进行的比较是不同的。
Let’s say we have two BigDecimal objects, bd1 and bd2. If bd1.compareTo(bd2) == 0, it only indicates the two BigDecimals are equal in value. For example, BigDecimal 42.00 and 42.0000 are equal in value but different in scale:
假设我们有两个 BigDecimal 对象,即 bd1 和 bd2。如果 bd1.compareTo(bd2) == 0,则仅表示这两个 BigDecimal 的值相等。例如,BigDecimal 42.00 和 42.0000 的值相等,但比例不同:
BigDecimal bd1 = new BigDecimal("42.00");
BigDecimal bd2 = new BigDecimal("42.0000");
assertEquals(0, bd1.compareTo(bd2));
However, it’s important to note that the equals() method in BigDecimal evaluates equality based on both value and scale. Therefore, comparing BigDecimal 42.00 with 42.0000 using the equals() method would result in them being considered unequal:
但是,需要注意的是,BigDecimal 中的 equals() 方法根据值和比例来评估相等性。因此,使用 equals() 方法比较 BigDecimal 42.00 和 42.0000 将导致它们被视为不相等:
BigDecimal bd1 = new BigDecimal("42.00");
BigDecimal bd2 = new BigDecimal("42.0000");
assertNotEquals(bd1, bd2);
So, next, let’s compare BigDecimal.ZERO and new BigDecimal(0) using the equals() method:
接下来,让我们使用 equals() 方法比较 BigDecimal.ZERO 和 new BigDecimal(0) :
BigDecimal zero = BigDecimal.ZERO;
BigDecimal zero0 = new BigDecimal(0);
assertEquals(zero, zero0);
As demonstrated by the test above, BigDecimal.ZERO and new BigDecimal(0) exhibit equality in both value and scale. Consequently, they’re mathematically the same. In practical terms, this implies that there is no perceptible difference when employing them in calculations.
如上面的测试所示,BigDecimal.ZERO和new BigDecimal(0) 在值和比例上都是相等的。因此,它们在数学上是相同的。在实际应用中,这意味着在计算中使用它们时没有明显的区别。
Next, let’s have a look at how these two objects get instantiated.
接下来,让我们看看这两个对象是如何实例化的。
3. How Does BigDecimal.ZERO Work Internally?
3.BigDecimal.ZERO 内部是如何工作的?
BigDecimal.ZERO is a constant field in the BigDecimal class:
BigDecimal.ZERO 是 BigDecimal 类中的一个常量字段:
public static final BigDecimal ZERO = ZERO_THROUGH_TEN[0];
As we can see, it takes the first element from an array called ZERO_THROUGH_TEN:
我们可以看到,它从名为 ZERO_THROUGH_TEN: 的数组中获取第一个元素。
private static final BigDecimal[] ZERO_THROUGH_TEN = {
new BigDecimal(BigInteger.ZERO, 0, 0, 1),
new BigDecimal(BigInteger.ONE, 1, 0, 1),
new BigDecimal(BigInteger.TWO, 2, 0, 1),
...
new BigDecimal(BigInteger.TEN, 10, 0, 2),
};
BigDecimal pre-instantiated eleven objects (0 to 10). So, BigDecimal.ZERO and other instances in the array are readily available for use without the need for additional object creation.
BigDecimal 预先实例化了 11 个对象(0 至 10)。因此,BigDecimal.ZERO 和数组中的其他实例可随时使用,而无需创建其他对象。
Therefore, whenever we use BigDecimal.ZERO, we’re referencing the same object:
因此,无论我们使用 BigDecimal.ZERO 还是使用 BigDecimal.ZERO 时,我们都在引用同一个对象:。
BigDecimal z1 = BigDecimal.ZERO;
BigDecimal z2 = BigDecimal.ZERO;
assertSame(z1, z2);
4. How Does new BigDecimal(0) Work Internally?
4.new BigDecimal(0) 内部是如何工作的?
On the other hand, new BigDecimal(0) creates a new BigDecimal object with the constructor by specifying the value 0:
另一方面,new BigDecimal(0) 通过指定值 0 使用构造函数创建一个新的 BigDecimal 对象:
public BigDecimal(int val) {
this.intCompact = val;
this.scale = 0;
this.intVal = null;
}
As it invokes the constructor, every time we call new BigDecimal(0), a new object is created:
在调用构造函数时,每次调用 new BigDecimal(0) 时,都会创建一个新对象:
BigDecimal z1 = new BigDecimal(0);
BigDecimal z2 = new BigDecimal(0);
assertNotSame(z1, z2);
5. Which Approach Should We Take?
5.我们应该采取哪种方法?
Both BigDecimal.ZERO and new BigDecimal(0) approaches create immutable BigDecimal objects, ensuring thread safety and consistency. However, as we discussed earlier, BigDecimal.ZERO has the additional advantage of reusing a shared constant object. When BigDecimal.ZERO is used across multiple parts of the codebase, the same object reference is employed, avoiding unnecessary object creation.
BigDecimal.ZERO 和 new BigDecimal(0) 方法都会创建不可变的 BigDecimal 对象,从而确保线程安全和一致性。但是,正如我们前面所讨论的,BigDecimal.ZERO 还具有重复使用共享常量对象的额外优势。在代码库的多个部分使用 BigDecimal.ZERO 时,将使用相同的对象引用,从而避免创建不必要的对象。
Additionally, one of the primary considerations when choosing between BigDecimal.ZERO and new BigDecimal(0) is the clarity and intent the code conveys. BigDecimal.ZERO is widely favored for its readability and conciseness. Its self-explanatory nature makes the code more expressive and aligns with the clear intent of representing 0.
此外,在BigDecimal.ZERO和new BigDecimal(0)之间进行选择时,主要考虑因素之一是代码所传达的清晰度和意图。BigDecimal.ZERO因其可读性和简洁性而广受青睐。其不言自明的性质使代码更具表现力,并与表示 0 的明确意图相一致。
Hence, opting for BigDecimal.ZERO is advisable when our intent is to have a BigDecimal object representing the value 0.
因此,当我们希望使用 BigDecimal.ZERO 对象来表示数值 0 时,选择 BigDecimal.ZERO 是明智的。
6. Conclusion
6.结论
In this article, we first learned how BigDecimal.ZERO and new BigDecimal(0) approaches instantiate a BigDecimal instance. Then, we discussed which approach we should take from the readability and object reuse perspectives.
在本文中,我们首先了解了 BigDecimal.ZERO 和 new BigDecimal(0) 如何实例化 BigDecimal 实例。然后,我们从可读性和对象重用的角度讨论了应该采用哪种方法。
BigDecimal.ZERO stands out for its concise syntax, clear intent, and the potential for shared object references. So, the BigDecimal.ZERO approach should be our first choice if we want a BigDecimal object to represent the value 0.
BigDecimal.ZERO因其简洁的语法、明确的意图和共享对象引用的潜力而脱颖而出。因此,如果我们要使用 BigDecimal.ZERO 对象来表示值 0,BigDecimal.ZERO 方法应该是我们的首选。
As always, the complete source code for the examples is available over on GitHub.
与往常一样,这些示例的完整源代码可在 GitHub 上获取。