I am totally a newbie when it comes to Groovy, and when using it a bit of for our CI (Jenkins), I stumbled upon the non-intuitive difference between a Groovy and a Java String.
Some code
Just put some items in a Set, and look for it:
Set<String> s = new HashSet<String>();
def artifactId = "commons-lang3"
def version = "3.17.0"
def jarName = "${artifactId}-${version}.jar"
s.add(jarName)
println(s.contains("commons-lang3-3.17.0.jar")) // false
I first thought it was some white space problems, so I tried to trim()
the string… and it worked! But there was no white space.
Set<String> s = new HashSet<String>();
def artifactId = "commons-lang3"
def version = "3.17.0"
def jarName = "${artifactId}-${version}.jar"
s.add(jarName.trim())
println(s.contains("commons-lang3-3.17.0.jar")) // true
Not the same String
A Groovy String is not a Java string, that’s all…:
def jarName1 = "${artifactId}-${version}.jar"
def jarName2 = artifactId + "-" + version + ".jar"
println(jarName2.equals(jarName1)) // false
println(jarName1.equals(jarName2.trim())) // false
println(jarName2.equals(jarName1.trim())) // true
println(jarName1.getClass().getSimpleName()) // GStringImpl
println(jarName2.getClass().getSimpleName()) // String
println(jarName1.toString()) // String
So depending on the type of string used in a Set or a Map, it may find them or not depending on which version is used.
What I find worse, is that calling trim()
on a GString
actually returns a Java String
and not a GString
.
Conclusion
Read the documentation…
Despite the behavior being documented on the Groovy website, I find it totally unintuitive, and very prone to subtle bugs…
I hate Groovy.