Course – LS – All

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

>> CHECK OUT THE COURSE

1. Overview

In this tutorial, we’ll explore two effective approaches for converting a Long to a BigDecimal in Java.

2. Introduction to the Problem

When we talk about converting Long to BigDecimal, some may think both are in the Number type, so we could probably cast Long to BigDecimal like BigDecimal bd = (BigDecimal) longValue.

However, this doesn’t compile:

java: incompatible types: java.lang.Long cannot be converted to java.math.BigDecimal

So next, let’s explore a couple of ways to convert Long to BigDecimal.

For simplicity, we’ll use unit test assertions to verify whether each approach works as expected.

3. Using the BigDecimal Constructor

The BigDecimal class provides a constructor to accept a long value and create a BigDecimal instance. Next, let’s create a test to check if this approach works for our needs:

Long num4 = 4L;
BigDecimal result4 = new BigDecimal(num4);
assertEquals(new BigDecimal("4"), result4);

Long num42 = -42L;
BigDecimal result42 = new BigDecimal(num42);
assertEquals(new BigDecimal("-42"), result42);

As we can see, we tested positive and negative Long values. After we called the constructor, we got the expected BigDecimal objects.

4. Using the BigDecimal.valueOf() Method

The BigDecimal class also provides a static method to create a BigDecimal object from a given long value: BigDecimal.valuOf().

Next, let’s see how to use this method:

Long num4 = 4L;
BigDecimal result4 = BigDecimal.valueOf(num4);
assertEquals(new BigDecimal("4"), result4);

Long num42 = -42L;
BigDecimal result42 = BigDecimal.valueOf(num42);
assertEquals(new BigDecimal("-42"), result42);

5. Which One to Use?

We’ve seen two ways to create a BigDecimal object from a long value: the BigDecimal(long val) constructor and the static method BigDecimal.valueOf(long val). Some may ask, which method to choose when we convert Long to BigDecimal?

Let’s first answer the question: we should use the static method over the constructor. Next, we’ll understand why the static method is a better choice.

To understand the difference between these two approaches, let’s look at the implementation of the valueOf() method:

public static BigDecimal valueOf(long val) {
    if (val >= 0L && val < (long)ZERO_THROUGH_TEN.length) {
        return ZERO_THROUGH_TEN[(int)val];
    } else {
        return val != Long.MIN_VALUE ? new BigDecimal((BigInteger)null, val, 0, 0) : new BigDecimal(INFLATED_BIGINT, val, 0, 0);
    }
}

As the code above shows, the method checks that if the given long value is between 0 and 10, it returns the corresponding element from the array ZERO_THROUGH_TEN.

Next, let’s look at what we have in the ZERO_THROUGH_TEN array:

public class BigDecimal ... {
    ...
    private static final BigDecimal[] ZERO_THROUGH_TEN;
    ...
    static {
        ZERO_THROUGH_TEN = new BigDecimal[]{
          new BigDecimal(BigInteger.ZERO, 0L, 0, 1), 
          ...
          new BigDecimal(BigInteger.valueOf(9L), 9L, 0, 1),
          new BigDecimal(BigInteger.TEN, 10L, 0, 2)};

       ... 
...}
}

As we can see, ZERO_THROUGH_TEN is a static BigDeicmal array, which is initialized in a static block. Therefore, the BigDeicmal class caches value 0 to 10 in the ZERO_THROUGH_TEN array.

So, when we call BigDecimal.valueOf(), if the long value is between 0 and 10, valueOf() immediately gives us the cached object from the ZERO_THROUGH_TEN array. Otherwise, it constructs a new BigDecimal object. 

Next, let’s verify it by a test:

Long num4 = 4L;
BigDecimal bd4_1 = BigDecimal.valueOf(num4);
BigDecimal bd4_2 = BigDecimal.valueOf(num4);
BigDecimal bd4_3 = BigDecimal.valueOf(num4);
assertSame(bd4_1, bd4_2);
assertSame(bd4_2, bd4_3);

Long num42 = -42L;
BigDecimal bd42_1 = BigDecimal.valueOf(num42);
BigDecimal bd42_2 = BigDecimal.valueOf(num42);
BigDecimal bd42_3 = BigDecimal.valueOf(num42);
assertNotSame(bd42_1, bd42_2);
assertNotSame(bd42_1, bd42_3);
assertNotSame(bd42_2, bd42_3);

As we can see, we called BigDecimal.valueOf(num4) three times. The method returns the same cached object. But when the long value isn’t between 0 and 10, the method always returns a new object.

On the other hand, every time we call the constructor, the BigDecimal class constructs a different object for us:

Long num4 = 4L;
BigDecimal result1 = new BigDecimal(num4);
BigDecimal result2 = new BigDecimal(num4);
BigDecimal result3 = new BigDecimal(num4);
assertNotSame(result1, result2);
assertNotSame(result2, result3);
assertNotSame(result1, result3);

Long num42 = -42L;
BigDecimal bd42_1 = new BigDecimal(num42);
BigDecimal bd42_2 = new BigDecimal(num42);
BigDecimal bd42_3 = new BigDecimal(num42);
assertNotSame(bd42_1, bd42_2);
assertNotSame(bd42_1, bd42_3);
assertNotSame(bd42_2, bd42_3);

6. Conclusion

In this article, we’ve learned two ways to convert a Long value to a BigDecimal object.

In practice, we should use BigDecimal.valueOf() over the constructor, as valueOf() can utilize cached objects if the long value is between 0 and 10.

As usual, all code snippets presented in the article are 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.