Why S2129 - BigDecimal constructors are not the same as values

java

(Stephen Palmer) #1

Template for a good false-positive report:

  • SonarQube LTS

Java rule S2129 says not to use new BigDecimal(double) and to use Bigdecimal.valueOf(double) instead but these do subtly different things. Also claims constructors are deprecated in Java 9 but I do not see this in the oracle javadocs for java 9 or 10


(Nicolas Peru) #2

What is the SonarJava version installed on your SonarQube instance ?


(Stephen Palmer) #3

Sonar Qube Version 6.7.4 (build 38452) with SonarJava 5.5 I believe


(Nicolas Bontoux) #4

This is the SonarQube version @stephenrpalmer. What @Nicolas_Peru is seeking here is the precise version of the analyzer inspecting Java code (what he called SonarJava).

If you have admin rights: go in the Marketplace and/or check your System Info JSON, you’ll be able to get the detailed version of the embedded analyzers.

If you don’t have admin rights, check-out the debug logs of your analysis (sonar.verbose=true).


(Stephen Palmer) #5

I can only confirm SonarJava version tomorrow but I believe it to be 5.5 (that was what was communicated last)


(Adam Gabryś) #6

Hi,
In this case Stephen didn’t find that the rule works invalid. I think he wants to let you know that the rule has incorrect description.

Constructors for Strings , BigInteger , BigDecimal and the objects used to wrap primitives should never be used. Doing so is less clear and uses more memory than simply using the desired value in the case of strings, and using valueOf for everything else.

Further, these constructors are deprecated in Java 9, which is an indication that they will eventually be removed from the language altogether.

It points that:

  • constructors are deprecated (not true)

  • use BigDecimal.valueOf(1.1) instead of new BigDecimal(1.1), but those two operations create different objects:

    @Test
    public void test() {
        final BigDecimal decimal1 = new BigDecimal(1.1);
        final BigDecimal decimal2 = BigDecimal.valueOf(1.1);
    
        assertThat(decimal1).isEqualTo(decimal2);
    }
    

    result:

    expected:<1.1[]> but was:<1.1[00000000000000088817841970012523233890533447265625]>
    

    so it is not a safe “use instead of” operation.

See also:

Cheers