javastringgroovyapache-stringutilsstring-utils

Calling Java Apache StringUtils.join() from Groovy


I am attempting to call the Apache Commons StringUtils.join() method from within a Groovy class. I want to concatenate 3 strings (part1, part2, and part3).

Why doesn't this work?

def path = StringUtils.join([part1, part2, part3]) //1

But the following line works:

def path = StringUtils.join([part1, part2, part3] as String[]) //2

A follow up question. Why does this work? I am using StringUtils v 2.6, so it does not have a varargs method. Does groovy always convert method parameters to an array?

def path = StringUtils.join(part1, part2, part3)  //3

This is largely a curiosity question. I am not going to use StringUtils because I posted a separate question yesterday and found a better solution. However, I would still like to understand why technique #1 does not work, yet #3 does work.


Solution

  • So, to show what is happening, let's write a script and show what output we get:

    @Grab( 'commons-lang:commons-lang:2.6' )
    import org.apache.commons.lang.StringUtils
    
    def (part1,part2,part3) = [ 'one', 'two', 'three' ]
    
    def path = StringUtils.join( [ part1, part2, part3 ] )
    println "1) $path"
    
    path = StringUtils.join( [ part1, part2, part3 ] as String[] )
    println "2) $path"
    
    path = StringUtils.join( part1, part2, part3 )
    println "3) $path"
    

    This prints:

    1) [one, two, three]
    2) onetwothree
    3) onetwothree
    

    Basically, the only one of your method calls that matches a signature in the StringUtils class is 2), as it matches the Object[] method definition. For the other two, Groovy is picking the best match that is can find for your method call.

    For both 1) and 3), it's doing the same thing. Wrapping the parameters as an Object[] and calling the same method as 2)

    For 3) this is fine, as you get an Object[] with 3 elements, but for 1), you get an Object[] with one element; your List.

    A way of getting it to work with the List parameter, would be to use the spread operator like so:

    path = StringUtils.join( *[ part1, part2, part3 ] )
    println "4) $path"
    

    Which would then print:

    4) onetwothree
    

    As expected (it would put all the elements of the list in as separate parameters, and these would then be put into an Object[] with three elements as in example 3)