In the first part of the series, we covered the first steps in writing Groovy scripts, including closures, concise syntax, and the language’s basic data types. This second instalment looks at features that make Groovy especially approachable for Java developers: flexible conditional evaluation, native regular expressions, operator methods, and simple property declarations.
The Groovy Truth
Java requires a condition to resolve to a boolean value. Groovy broadens that model with a set of runtime rules often called Groovy Truth. Rather than requiring an explicit comparison in every case, common values can be evaluated directly in a condition.
| Type | Evaluates as true when |
|---|---|
| Boolean | The value is true. |
| Matcher | At least one match is present. |
| Collection | The collection is not empty. |
| Map | The map is not empty. |
| String or GString | The string contains characters. |
| Number or character | The value is not zero. |
| Other objects | The reference is not null. |
The relevant type is determined at runtime. That small shift makes conditional code more compact while preserving the intent of a test.
Regular expressions
Groovy gives regular expressions direct language support. A slash-delimited expression can be used without the escaping ceremony often needed when a pattern is written as a Java string. The language also provides operators for searching, checking a complete match, and creating a compiled pattern.
=~searches for a match and returns a matcher.==~checks whether an entire value matches and returns a boolean.~produces a compiled pattern.
Listing 3.1 · Matching text
def text = "Groovy is a dynamic language"
assert text =~ /ua/
matcher = text =~ /ua/
assert matcher instanceof java.util.regex.Matcher
def match = text ==~ /.*ua.*/
assert match instanceof java.lang.Boolean
assert match
def pattern = ~/oovy/
def result = pattern.matcher(text)
assert result instanceof java.util.regex.Matcher
The first two forms search within the supplied text or check the whole text, while the final form compiles the expression for reuse. A compiled pattern can be the clearer choice when the same expression is applied repeatedly.
Operator overloading
Groovy maps many operators to methods with conventional names. Classes that provide those methods can participate in ordinary-looking expressions, keeping domain code readable without requiring special syntax at every call site.
| Operation | Method name |
|---|---|
a + b | a.plus(b) |
a - b | a.minus(b) |
a * b | a.multiply(b) |
a / b | a.div(b) |
Listing 4.1 · Operators in familiar form
text = "Programing" - "ing" + "er"
assert "Programer" == text
list = [1, 2, 3]
list += [4, 5, 6]
assert [1, 2, 3, 4, 5, 6] == list
list << 7
assert [1, 2, 3, 4, 5, 6, 7] == list
s = "A" * 5
assert s == "AAAAA"
These conventions also make it possible to shape small domain-specific languages. The useful question is not whether every operator can be overloaded, but whether an expression remains obvious to the next reader.
From POJOs to POGOs
Java developers are familiar with POJOs: small objects that keep application state and behaviour straightforward. Groovy offers a related convention commonly called a POGO, or Plain Old Groovy Object. A property declared without an access modifier receives accessor behaviour automatically, so repetitive getters and setters do not need to be written by hand.
Listing 5.1 · A simple POGO
class Person {
String name
String lastname
private int id
String toString() { "${name} ${lastname}" }
}
Person person = new Person(name: 'Andres', lastname: 'Almiray')
assert "Andres Almiray" == person.toString()
person.lastname = "Jaramillo"
assert "Andres Jaramillo" == person.toString()
person['lastname'] = "Almiray"
assert "Andres Almiray" == person.toString()
Named-style construction is available for the declared properties. Property access through dot notation is resolved through Groovy’s object model, and bracket notation may be used where it helps make dynamic access explicit. Direct field access is available with .@ when that distinction is genuinely required.
Listing 5.2 · Properties and fields
class Person {
String name
String lastname
private int id
String toString() { "${name} ${lastname}" }
def getFullName() { "${name} ${lastname}" }
}
Person person = new Person(name: 'Andres', lastname: 'Almiray')
assert person.name == "Andres"
assert person.@name == "Andres"
assert person.fullName == "Andres Almiray"
Conclusion
Groovy’s conditional rules, regular-expression support, operator conventions, and properties all aim at reducing incidental ceremony around ordinary programming tasks. For Java developers, the value is often in recognising where the language can make a small piece of code more direct while keeping its purpose clear.