Published
- 2 min read
Java 11 negative symbol in Swedish
We performed a migration to Java 11 and a bug fix about negative symbol for negative numbers in Java ruined our implementation. This article describes the situation and the lessons learned.
In the middle of a migration of a project to Java 11 a very curious scenario has appeared. We face a bug while dealing with negative numbers. We have a function to convert a positive number to negative. The implementation was working fine for Java 8 but not for Java 11:
public String negativeNumber(int number) {
return "-" + number;
}
The error appeared while trying to parse the numbers generated with that function:
public Number parse(String number) throws ParseException {
return fmt.parse(number)
}
More precisely, it was throwing the following exception:
Unparseable number: "-1"
java.text.ParseException: Unparseable number: "-1"
at java.base/java.text.NumberFormat.parse(NumberFormat.java:431)
at SwedishNegativeSymbol.shouldParseNegativeNumberButFailsOnJava11(SwedishNegativeSymbol.java:23)
The investigation and debug led us to compare our negative symbol with the one expected by the NumberFormat
:
@Test
public void shouldUseSameNegativeSymbol() {
String expectedNegativeSymbol = fmt.getNegativePrefix();
String negativeSymbol = negate(1).substring(0, 1);
assertEquals("Negative symbols do not match!", expectedNegativeSymbol, negativeSymbol);
}
And… surprise, the test pass on Java 8 but not in Java 11:
Negative symbols do not match! expected:<[−]> but was:<[-]>
Expected :−
Actual :-
org.junit.ComparisonFailure: Negative symbols do not match! expected:<[−]> but was:<[-]>
at org.junit.Assert.assertEquals(Assert.java:115)
at SwedishNegativeSymbol.shouldUseSameNegativeSymbol(SwedishNegativeSymbol.java:35)
WTF!. Why on earth the negative symbol do not match? The response is here: JDK-8214926.
It looks like the negative symbol returned in Java 8 was wrong and Java authors decided to fix that in Java11. The two characters are visually very similar:
The solution was straightforward: use the negative symbol provided by NumberFormat
public String negativeNumberWorkingOnJava11(int number) {
DecimalFormat fmt = (DecimalFormat) NumberFormat.getInstance(Locale.forLanguageTag("se-sv"));
return fmt.getNegativePrefix() + number;
}
Now the test passes both in Java 8 and Java 11.
The lesson learned was important: DO NOT HARDCODE NEGATIVE SYMBOL!
You can find the source code here: SwedishNegativeSymbol.java