Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Equals over String literal and String coming from NumberFormat fails due to different byte representation

Tags:

java

java-9

I was playing around with Java 9 with the prod code. And I found a couple of Formatting tests failing. After some research, I was able to create a class to reproduce the issue. Which happens in Java 9 but not in Java 8.

The class is here https://pastebin.com/87sA5WMb

import java.text.*;
import java.util.*;

public class FormatFails {
    public static void main(String... args){

        Currency currency = Currency.getInstance("EUR");
        NumberFormat currencyFormatter = NumberFormat.getCurrencyInstance(Locale.FRANCE);
        currencyFormatter.setMaximumFractionDigits(0);
        currencyFormatter.setMinimumFractionDigits(0);
        currencyFormatter.setCurrency(currency);

        String expected = "123 457 €";
        String obtained = currencyFormatter.format(123456.789);
        System.out.println(expected);
        System.out.println(obtained);
        System.out.println(expected.equals(obtained));

        System.out.format("Bytes from expected: %s\n",Arrays.toString(expected.getBytes()));
        System.out.format("Bytes from obtained: %s\n",Arrays.toString(obtained.getBytes()));       
    }

}

Basically comparing 2 strings:

  • An string literal and
  • A formatted string in Locale.FRANCE produced using NumberFormat

Using equals on both fails, because of the following:

123 457 €
123 457 €
false
Bytes from expected: [49, 50, 51, -62, -96, 52, 53, 55, 32, -30, -126, -84]
Bytes from obtained: [49, 50, 51, -62, -96, 52, 53, 55, -62, -96, -30, -126, -84]

As you can see there are a different number of bytes and different representation. I don't know how to work around this and more important which is the change in Java9 that is affecting the code.

The result using plain old Java 8 is as follows:

123 457 €
123 457 €
true
Bytes from expected: [49, 50, 51, -62, -96, 52, 53, 55, 32, -30, -126, -84]
Bytes from obtained: [49, 50, 51, -62, -96, 52, 53, 55, 32, -30, -126, -84]

Java 9 version used

java version "9"
Java(TM) SE Runtime Environment (build 9+181)
Java HotSpot(TM) 64-Bit Server VM (build 9+181, mixed mode)

which is the latest version available.

like image 279
xiumeteo Avatar asked Sep 06 '17 22:09

xiumeteo


1 Answers

JDK 9 has moved to use CDLR locale data by default. Links to the JEP and more information on this can be found in the JDK 9 release notes (see http://jdk.java.net/9/release-notes#JDK-8008577). The release note and JEP document the system property can you can use to configure the JDK to use the legacy JRE locale data where needed.

like image 66
Alan Bateman Avatar answered Oct 23 '22 15:10

Alan Bateman