Control Flow and Groovy Truth
8.1 Groovy Truth
"" (empty string/GString) Empty collection/map/array Matcher without a match Iterator/Enumeration with no elements
Object with asBoolean() returning false
if ([]) println "won't print"
if ("text" && [1] && 42) println "all truthy"
def name = ""
println name ?: "default"8.2 if / else and the Ternary
if (x > 0) println "positive"
else if (x < 0) println "negative"
else println "zero"
def label = x > 0 ? "pos" : "non-pos"8.3 Powerful switch
Cases use isCase(): values (equals), classes (instanceof), ranges/collections (contains), regex (match), closures (truthy result).
def describe(x) {
switch (x) {
case null: return "null"
case 0: return "zero"
case Integer: return "integer" // type check
case 1..9: return "digit" // range
case ['a', 'b', 'c']: return "abc" // list membership
case ~/\d+/: return "numeric string" // regex
case { it instanceof String && it.size() > 10 }: return "long string" // closure
default: return "other"
}
}8.4 Switch Expressions (Groovy 4)
def result = switch (day) {
case 'SAT', 'SUN' -> 'weekend'
case ~/^MON|TUE|WED|THU|FRI$/ -> 'weekday'
default -> {
println "unknown"
'invalid'
}
}8.5 Loops
break/continue don't work inside each closures. Use for loops, find/any (which short-circuit), or return (which skips to the next element).
for (int i = 0; i < 3; i++) println i // classic
for (i in 0..<3) println i // for-in over a range
for (item in ['a', 'b']) println item
for (entry in [a: 1, b: 2]) println "$entry.key=$entry.value"
for (def (i, j) = [0, 0]; i < 3; i++, j += 2) {} // multi-assignment in a for loop (Groovy 3+)
def n = 0
while (n < 5) n++
do { n-- } while (n > 0) // do-while (Groovy 3+)
3.times { println it }
[1, 2, 3].each { println it }
[1, 2, 3].eachWithIndex { v, i -> println "$i: $v" }
outer:
for (i in 1..3) {
for (j in 1..3) {
if (i * j == 4) break outer
if (j > i) continue outer
}
}