Variables, Types and Optional Typing

4.1 Declaring Variables

In scripts, assigning to an undeclared variable puts it in the script binding (global-like): counter = 0.

def name = "Groovy"          // dynamic type (Object reference, holds a String)
var count = 10               // same as def (Groovy 3+)
String lang = "Groovy"       // static type declaration
int age = 30                 // primitive (optimized)
final pi = 3.14159           // can't be reassigned

def (a, b, c) = [1, 2, 3]    // multiple assignment
def (x, y) = "10 20".split()*.toInteger()
(a, b) = [b, a]              // swap
def (first, second) = [1]    // second == null

4.2 Dynamic vs Static Types

Types are checked at runtime unless @TypeChecked / @CompileStatic is used (Module 23).

def value = 42
value = "now a string"        // allowed: def is dynamic
String s = "text"
// s = 42                     // runtime cast attempt: s becomes "42" (GString/Object → String coercion)
Integer n = "42" as Integer   // explicit coercion with `as`

4.3 Primitive and Wrapper Types

Default literal type byte, short, int, long Integer literals are Integer, then Long, then BigInteger as needed float, double

Decimal literals are BigDecimal by default No char literal ('a' as char) true / false

4.4 Checking Types

def v = 3.14
println v.class                    // class java.math.BigDecimal
println v instanceof Number        // true
println v.getClass().simpleName
if (v in BigDecimal) println "BigDecimal"   // `in` with a class calls isCase → instanceof