Why does String.replaceAll() work differently in Java 8 from Java 9?

JavaRegexStringJava 8Java 9

Java Problem Overview


Why does this code output 02 in [tag:java-8] but o2 in [tag:java-9] or above?

"o2".replaceAll("([oO])([^[0-9-]])", "0$2")

Java Solutions


Solution 1 - Java

Most likely due to JDK-6609854 and JDK-8189343 which reported negative nested character classes handling (in your example [^[0-9-]]). This behavior was fixed in 9 and 10, but fix was not backported to 8. The bug for Java 8 is explained as:

> In Java, the negation does not apply to anything appearing in > nested [brackets] > > So [^c] does not match "c", as you would expect. > > [^[c]] does match "c". Not what I would expect. > > [[^c]] does not match "c" > > The same holds true for ranges or property expressions - if they're > inside brackets, a negation at an out level does not affect them. > > [^a-z] is opposite from [^[a-z]]

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionFuyang LiuView Question on Stackoverflow
Solution 1 - JavaKarol DowbeckiView Answer on Stackoverflow