Course – LS – All

Get started with Spring and Spring Boot, through the Learn Spring course:

>> CHECK OUT THE COURSE

1. Overview

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).

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

Before we compare BigDecimal.ZERO and new BigDecimal(0), let’s quickly see how to compare two BigDecimal objects.

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.

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 = 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 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:

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.

Next, let’s have a look at how these two objects get instantiated.

3. How Does BigDecimal.ZERO Work Internally?

BigDecimal.ZERO is a constant field in the BigDecimal class:

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:

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.

Therefore, whenever we use BigDecimal.ZERO, we’re referencing the same object:

BigDecimal z1 = BigDecimal.ZERO;
BigDecimal z2 = BigDecimal.ZERO;
assertSame(z1, z2);

4. How Does new BigDecimal(0) Work Internally?

On the other hand, new BigDecimal(0) creates a new BigDecimal object with the constructor by specifying the value 0:

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:

BigDecimal z1 = new BigDecimal(0);
BigDecimal z2 = new BigDecimal(0);
assertNotSame(z1, z2);

5. Which Approach Should We Take?

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.

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.

Hence, opting for BigDecimal.ZERO is advisable when our intent is to have a BigDecimal object representing the value 0.

6. Conclusion

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 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.

As always, the complete source code for the examples is available over on GitHub.

Course – LS – All

Get started with Spring and Spring Boot, through the Learn Spring course:

>> CHECK OUT THE COURSE
res – REST with Spring (eBook) (everywhere)
Comments are open for 30 days after publishing a post. For any issues past this date, use the Contact form on the site.