GStrings: Groovy's Interpolated Strings
A Groovy string written with double quotes and containing a ${...} or $name placeholder becomes a GString (groovy.lang.GString), a distinct type from java.lang.String that lazily evaluates its embedded expressions each time it's converted to a string, whereas single-quoted strings in Groovy are always plain, non-interpolating java.lang.String literals.
Cricket analogy: A GString is like a live scoreboard graphic that recalculates Score: ${runs}/${wickets} fresh every time the broadcast cuts to it, whereas a single-quoted plain String is like a printed scorecard from the tea interval that never updates again.
Interpolation Syntax
Groovy supports two interpolation forms: the short $identifier form for a simple variable or property reference like "Hello $name", and the full ${expression} form for arbitrary expressions, method calls, or multi-part paths like "Total: ${price * qty}" - the braces are required whenever the expression is more than a bare identifier or dotted property chain.
Cricket analogy: The short $playerName form is like a commentator casually dropping a player's name mid-sentence, while the full ${player.average * overs} form is like the broadcast needing a full stats-graphics package because the expression involves a calculation, not just a name.
def name = 'Ada'
def price = 19.99
def qty = 3
def greeting = "Hello, $name!"
def receipt = "Total: ${price * qty}"
println greeting.class // class org.codehaus.groovy.runtime.GStringImpl
println receipt // Total: 59.97
// GString vs String map-key pitfall
def key = "${name}"
def map = ['Ada': 'admin']
println map[key] // null - GString key doesn't match String key
println map[key.toString()] // admin
GString vs String Identity and Equality
Because a GString is a different class from String, code that does identity-sensitive things - like using a value as a Map key, comparing with == against a literal String, or matching a switch case - can behave unexpectedly, since GString.equals(String) returns false even when the rendered text matches; the safe practice is to call .toString() before using an interpolated value anywhere strict String typing or hashing matters.
Cricket analogy: Using a GString as a lookup key that fails to match a plain-String key in a stats map is like a scorer filing an innings under a computed live label that a lookup for the pre-printed roster entry fails to find, because the two labels were built differently even though they read the same.
A GString used directly as a Map key is a classic bug source: map["${name}"] = 'x' followed by map['Ada'] can return null because the two keys hash and equal differently, even though both display as 'Ada'. Always call .toString() on an interpolated value before using it as a map key, in a switch statement, or anywhere else strict String equality is required.
Multi-line and Lazy Evaluation
Triple-quoted strings ("""...""") support multi-line GStrings with interpolation preserved across line breaks, and because a GString stores its embedded expressions as value objects rather than pre-rendering them, re-invoking .toString() on the same GString after the referenced variable changes produces updated output - interpolation is evaluated at stringification time, not at the moment the GString literal was written.
Cricket analogy: A GString scoreboard summary re-evaluating after runs changes is like a live TV graphic that recomputes Score: ${runs}/${wickets} the instant a boundary is scored, rather than a printed scorecard from over 10 that never reflects what happened in over 30.
- A GString is created by double-quoted strings containing $identifier or ${expression} placeholders; single-quoted strings never interpolate.
- The short $identifier form works for a bare variable or dotted property chain; the full ${expression} form is required for arbitrary expressions and method calls.
- GString is groovy.lang.GString, a class distinct from java.lang.String, so GString.equals(String) returns false.
- Using a GString as a Map key can silently fail to match a plain String key with the same rendered text.
- Call .toString() on a GString before using it anywhere strict String identity, hashing, or switch matching is required.
- Triple-quoted """...""" strings support multi-line GStrings with interpolation preserved.
- GString interpolation is evaluated lazily at stringification time, not at the moment the literal is written.
Practice what you learned
1. What type is produced by "Hello $name" in Groovy?
2. Which string literal form never interpolates in Groovy?
3. Why might map[gstringKey] return null even though map[gstringKey.toString()] returns a value?
4. When is the ${} braces form required instead of the short $identifier form?
5. When is a GString's embedded expression actually evaluated?
Was this page helpful?
You May Also Like
Optional Typing in Groovy
How Groovy lets you mix def (dynamic) and explicit static types, and how @TypeChecked and @CompileStatic add compile-time safety and performance.
Groovy Collections
How Groovy's native list and map literals, GDK methods like collect/findAll/inject/groupBy, ranges, and the spread operator make collection processing concise.
Operators and Truth in Groovy
Groovy's safe navigation, Elvis, and spaceship operators, operator overloading, and the rules of Groovy Truth for evaluating objects in boolean contexts.
Related Reading
Related Study Notes in Programming
Browse all study notesApache Spark Study Notes
Programming · 30 topics
ProgrammingApache Flink Study Notes
Programming · 30 topics
ProgrammingHadoop Study Notes
Programming · 30 topics
ProgrammingSnowflake Study Notes
Programming · 30 topics
ProgrammingApache Airflow Study Notes
Programming · 30 topics
Programmingdbt (Data Build Tool) Study Notes
Programming · 30 topics