Question

I saw this piece of code in the Groovy tutorial -

import groovy.sql.Sql
sql = Sql.newInstance( 'jdbc:jtds:sqlserver://serverName/dbName-CLASS;domain=domainName', 'username', 'password', 'net.sourceforge.jtds.jdbc.Driver' )
sql.eachRow( 'select * from tableName' ) { println "$it.id -- ${it.firstName} --" }

And it is the first occurrence of Groovy expressions (anything inside a ${} gets evaluated as an expression, not a string). My question is, does this Groovy expression feature actually provide some new functionality? It seems to me like there is nothing here that can be done with a good old string concat. IE -

println it.id + " -- " + it.firstName + " --"
Était-ce utile?

La solution

Yes. That's what they are. Being able to add code and variables into strings is a feature of Groovy that make Groovy groovy. String in Groovy can be just like templates.

Now, Groovy strings are enclosed in (") quotes. But a standard Java String in Groovy is enclosed in an apostrophe ('). Standard Java strings in groovy cannot contain variable references or code.

It makes code easier to read. Sometimes looking at all the '+' signs in Java as part of string concatenation is a PITA.

What would you rather code and read:

println "$it.id -- ${it.firstName} --"

or

println it.id + " -- " + it.firstName + " --"

Now, with local variables it becomes much easier to read too:

Groovy

def name = "some name"
def age = 30
def waist = 42
println "Did $name really have a size $waist waist at age $age?"

Java:

String name = "some name";
int age = 30;
int waistSize = 42;
System.out.println("Did " + name + " really have a " + waist + " waist at age  " age + "?";

Autres conseils

Another thing you can do with them is use them as slightly Lazy Templates, ie:

def x = "abc"

// Closure expansion rather than variable
def s = "x: ${->x}"

// Prints 'x: abc'
println s

// Change x
x = 400

// Prints 'x: 400'
println s

With the pure String concatenation, you'd end up writing a print function, or repeating your concatenation code

Also, don't forget the multi-line string operators -- such as """ -- and the stripMargin method which allows you to :

def (name,age,sender) = [ 'Alice', 30, 'Tim' ]
println """Hello $name
          |
          |$age today? Congratulations!
          |
          |$sender""".stripMargin()

Which prints:

Hello Alice

30 today? Congratulations!

Tim

Again, could be done with String concatenation, but ends up being loads more typing and error prone (imo)

Lots more about Groovy strings (various flavours) here: http://groovy.codehaus.org/Strings+and+GString

I believe any string of the form "a string" (i.e. double quotes) is an instance of GString in Groovy (not String). It is GString that provides these extra capabilities.

With the accepted answer here we seem to have landed on the conclusion that, yes, GString (i.e. a double-quoted string with one or more ${<expr>} expressions) is just syntax sugar. (I'm going by the first sentence of the accepted answer: "Yes. That's what they are.")

But that seems to be wrong because of lazy evaluation, as noted above by tim_yates.

Expanding a bit on the above, if one or more expressions in the string are closures, they are only evaluated when toString() is called on the GString. So, in groovyconsole:

def stime = "The time is: ${-> new Date().getTime()}."
println stime
Thread.sleep(500)
println stime
The time is: 1384180043679.
The time is: 1384180044194.

How would you do this with + without creating a new string every time? (The answer, in two Java projects I've worked on, was to invent a Template.java class, to do this sort of thing.) This suggests to me that there is more than just syntax sugar. Or perhaps that it is syntax sugar - but for the GString class, not for java.lang.String or strings generally.

Another example:

def vals = ['a':42]
def tmpl = "The answer is ${-> vals.a}."
println tmpl
vals.a = 43
println tmpl
The answer is 42.
The answer is 43.

I'm not sure I actually like this feature of GString; I'm sort of used to strings being immutable (coming from Java). Groovy's strings are not (quite). It seems like you ought to be able to assume that if two Groovy 'strings' reference the same instance, they will have the same textual value, but that is not quite true.

http://groovy.codehaus.org/Strings+and+GString (about halfway down)

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top