Static Type Checking and Static Compilation

23.1 @TypeChecked

Catches typos, missing methods, and wrong types at compile time. It keeps dynamic dispatch at runtime.

import groovy.transform.TypeChecked

@TypeChecked
class Calculator {
    int add(int a, int b) { a + b }
    void test() {
        // add("1", 2)        // compile error: cannot find matching method
        // def x = undefinedVar  // compile error
        String s = "text"
        // s.nonExistentMethod() // compile error
    }
}

23.2 @CompileStatic

Type checking plus static method dispatch (no MOP). It generates bytecode similar to Java's. It's much faster for CPU-bound code.

Trade-off: runtime metaprogramming (metaClass changes, methodMissing) is ignored for statically compiled call sites.

@CompileDynamic / @TypeChecked(TypeCheckingMode.SKIP) opt specific methods back out.

Apply globally with a compiler configuration script: withConfig(configuration) { ast(CompileStatic) } + groovyc --configscript config.groovy.

import groovy.transform.CompileStatic

@CompileStatic
class FastMath {
    static long fib(int n) { n < 2 ? n : fib(n - 1) + fib(n - 2) }   // Java-like speed
}

23.3 Flow Typing and Inference

@groovy.transform.TypeChecked
def flow() {
    def o = "string"
    o = o.toUpperCase()          // inferred String
    Object x = "abc"
    if (x instanceof String) {
        println x.length()       // smart cast after instanceof
    }
}

23.4 Closure Parameter Types: @ClosureParams and @DelegatesTo

import groovy.transform.stc.*
@groovy.transform.CompileStatic
void eachUser(List<String> users, @ClosureParams(value = SimpleType, options = "java.lang.String") Closure c) {
    users.each(c)
}

class EmailSpec { String to; String subject; void to(String t) { to = t } }
void email(@DelegatesTo(value = EmailSpec, strategy = Closure.DELEGATE_FIRST) Closure cl) {
    def spec = new EmailSpec()
    cl.delegate = spec
    cl.resolveStrategy = Closure.DELEGATE_FIRST
    cl()
}
email { to "[email protected]"; subject = "Hi" }     // the IDE and type checker know the delegate type

23.5 Type Checking Extensions

Custom scripts that teach the type checker about DSLs (@TypeChecked(extensions = 'MyExtension.groovy')). Groovy 4 added optional groovy-typecheckers (e.g., a regex checker and format string checker).