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

  • A+

Why does this code output 02 in but o2 in or above?

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


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 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]]


:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: