Beginner

Operators in Groovy

Learn arithmetic, comparison, logical, and Groovy-specific operators including Elvis, safe navigation, spaceship, range, and regex with Docker-ready examples

Introduction

Operators are the verbs of a programming language—they let you combine values, compare them, and express logic. Groovy inherits the full operator set from Java but layers on a handful of its own conveniences that make code dramatically more concise. Because Groovy is a multi-paradigm, dynamically typed (with optional static typing) language for the JVM, its operators work polymorphically: the same + can add numbers, concatenate strings, or merge lists depending on the operands.

A few aspects of Groovy’s operator design surprise newcomers. Dividing two integers with / does not produce an integer result—Groovy returns a BigDecimal to preserve precision. Comparison with == calls .equals() instead of doing reference comparison like Java. And uniquely Groovy operators like Elvis (?:), safe navigation (?.), spaceship (<=>), and ranges (..) eliminate huge amounts of defensive boilerplate.

In this tutorial you’ll work through the standard operator categories and then meet the Groovy-only operators that you’ll see constantly in Gradle build scripts, Jenkins pipelines, and Spock specifications.

Arithmetic, Comparison, Logical, and Assignment Operators

The first program covers the operators you’d recognize from any C-family language, plus a few quirks specific to Groovy’s numeric model.

Create a file named operators.groovy:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
// Arithmetic operators
int a = 17
int b = 5

println "a + b       = ${a + b}"
println "a - b       = ${a - b}"
println "a * b       = ${a * b}"
println "a / b       = ${a / b}"           // BigDecimal division, not truncated
println "a.intdiv(b) = ${a.intdiv(b)}"     // Integer division
println "a % b       = ${a % b}"
println "a ** b      = ${a ** b}"          // Power operator

// Comparison operators (== calls .equals(), not reference compare)
println "a == b: ${a == b}"
println "a != b: ${a != b}"
println "a > b:  ${a > b}"
println "'cat' == 'cat': ${'cat' == 'cat'}"

// Logical operators with short-circuit evaluation
boolean t = true
boolean f = false
println "t && f: ${t && f}"
println "t || f: ${t || f}"
println "!t:     ${!t}"

// Compound assignment
int x = 10
x += 5
println "x += 5  -> $x"
x *= 2
println "x *= 2  -> $x"
x -= 6
println "x -= 6  -> $x"

// String operators: + concatenates, * repeats
String s = "Hi"
println s + " there!"
println s * 3

A few things to notice:

  • 17 / 5 evaluates to 3.4, a BigDecimal. Use intdiv() when you want integer truncation.
  • ** is the power operator; Java has no equivalent.
  • == on strings tests content equality. To test object identity (Java’s ==), use is(): a.is(b).
  • * on a String repeats it, and + concatenates. These also work for lists.

Groovy-Specific Operators

Now we’ll meet the operators you don’t get in Java. Each one replaces a multi-line idiom with a single character or two.

Create a file named operators_special.groovy:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// Spaceship operator (<=>) — returns -1, 0, or 1
println "5 <=> 3: ${5 <=> 3}"
println "3 <=> 5: ${3 <=> 5}"
println "5 <=> 5: ${5 <=> 5}"

// Elvis operator (?:) — shorthand for "value or default"
def name = null
def displayName = name ?: "Anonymous"
println "Name: $displayName"

// Safe navigation (?.) — returns null instead of throwing NullPointerException
String text = null
println "Length: ${text?.length()}"

// Range operator (..) and 'in' membership operator
def range = 1..5
println "Range size: ${range.size()}"
println "3 in range: ${3 in range}"
println "9 in range: ${9 in range}"

// Regex find (=~) and exact match (==~)
def matcher = "Groovy 4.0" =~ /\d+/
println "First digits found: ${matcher[0]}"
println "'12345' ==~ /\\d+/: ${'12345' ==~ /\d+/}"
println "'abc12' ==~ /\\d+/: ${'abc12' ==~ /\d+/}"

Each of these collapses what would be several lines in Java:

  • Elvis (?:) replaces x != null ? x : default.
  • Safe navigation (?.) replaces x == null ? null : x.method().
  • Spaceship (<=>) is the natural fit for Comparator lambdas and sort keys.
  • Range (..) produces an iterable sequence; combined with in, it expresses membership cleanly.
  • =~ creates a java.util.regex.Matcher; ==~ returns true only when the entire string matches.

Operator Precedence

Groovy’s precedence rules follow Java’s closely. From highest to lowest, the groups you’ll encounter most often:

  1. Unary: !, - (negation), ++, --
  2. Power: **
  3. Multiplicative: *, /, %
  4. Additive: +, -
  5. Range: .., ..<
  6. Relational: <, >, <=, >=, in, instanceof
  7. Equality: ==, !=, <=>
  8. Logical AND: &&
  9. Logical OR: ||
  10. Ternary / Elvis: ?:
  11. Assignment: =, +=, -=, etc.

When in doubt, add parentheses—they cost nothing and make intent explicit.

Running with Docker

1
2
3
4
5
6
7
8
# Pull the official image
docker pull groovy:4.0-jdk17-alpine

# Run the basic operators example
docker run --rm -v $(pwd):/app -w /app groovy:4.0-jdk17-alpine groovy operators.groovy

# Run the Groovy-specific operators example
docker run --rm -v $(pwd):/app -w /app groovy:4.0-jdk17-alpine groovy operators_special.groovy

Expected Output

Running operators.groovy:

a + b       = 22
a - b       = 12
a * b       = 85
a / b       = 3.4
a.intdiv(b) = 3
a % b       = 2
a ** b      = 1419857
a == b: false
a != b: true
a > b:  true
'cat' == 'cat': true
t && f: false
t || f: true
!t:     false
x += 5  -> 15
x *= 2  -> 30
x -= 6  -> 24
Hi there!
HiHiHi

Running operators_special.groovy:

5 <=> 3: 1
3 <=> 5: -1
5 <=> 5: 0
Name: Anonymous
Length: null
Range size: 5
3 in range: true
9 in range: false
First digits found: 4
'12345' ==~ /\d+/: true
'abc12' ==~ /\d+/: false

Key Concepts

  • / is BigDecimal division, not integer truncation—use .intdiv() when you want a whole-number result.
  • == calls .equals() by default; reference identity is .is(). This is the opposite of Java and one of the most common stumbling points for Java developers.
  • ** is the power operator, eliminating the need for Math.pow() in most cases.
  • Elvis (?:) and safe navigation (?.) are everywhere in idiomatic Groovy—they replace null-check boilerplate.
  • Spaceship (<=>) returns -1, 0, or 1, making it the idiomatic key for sorting and Comparable implementations.
  • Ranges (.. inclusive, ..< exclusive) are first-class iterables and pair naturally with the in membership operator.
  • =~ returns a Matcher; ==~ returns a Boolean—remember “tilde for whole match” by the extra =.
  • Operator overloading is supported: define plus(), minus(), multiply(), compareTo(), etc., on your own classes and Groovy will wire them up to +, -, *, and <=>.

Running Today

All examples can be run using Docker:

docker pull groovy:4.0-jdk17-alpine
Last updated:

Comments

Loading comments...

Leave a Comment

2000 characters remaining