Skip to content

Groovy Classes from Java — Using Groovy in Java Projects

DodaTech Updated 2026-06-28 5 min read

In this tutorial, you will learn about Groovy Classes from Java. We cover key concepts, practical examples, and best practices to help you master this topic.

Groovy classes compile to JVM bytecode and can be used directly from Java, enabling gradual adoption of Groovy's productivity features in existing Java projects without rewriting.

What You'll Learn

  • Compiling Groovy classes for Java consumption
  • Calling Groovy methods from Java
  • Handling default parameters and closures
  • Gradle multi-language builds

Why It Matters

Teams can adopt Groovy incrementally — write new modules in Groovy while keeping existing Java code. Doda Browser uses Groovy for testing, build scripts, and rapid prototyping alongside its Java core.

Real-World Use

Gradual Migration from Java to Groovy, writing tests in Groovy for Java code (Spock), build logic (Gradle), and DSL components alongside Java business logic.

flowchart LR
    A["Groovy Class"] --> B["Compile .groovy"]
    B --> C[".class Bytecode"]
    C --> D["Java Uses It"]
    A --> E["@CompileStatic"]
    E --> F["Java-Friendly API"]
    style A fill:#2563eb,stroke:#2563eb,color:#fff
    style B fill:#dbeafe,stroke:#2563eb,color:#1e40af
    style C fill:#dbeafe,stroke:#2563eb,color:#1e40af
    style D fill:#dbeafe,stroke:#2563eb,color:#1e40af
    style E fill:#dbeafe,stroke:#2563eb,color:#1e40af

Writing Groovy for Java

// DataProcessor.groovy
import groovy.transform.CompileStatic

@CompileStatic
class DataProcessor {

    String process(String input) {
        input.trim().toUpperCase()
    }

    List<String> splitAndFilter(List<String> items, int minLength) {
        items.findAll { it.length() >= minLength }
    }

    static String format(String template, Map<String, Object> values) {
        values.inject(template) { acc, entry ->
            acc.replace("{{${entry.key}}}", entry.value.toString())
        }
    }
}

Using from Java

// JavaMain.java
public class JavaMain {
    public static void main(String[] args) {
        DataProcessor proc = new DataProcessor();

        // Call Groovy methods normally
        String result = proc.process("  hello world  ");
        System.out.println(result);  // HELLO WORLD

        List<String> filtered = proc.splitAndFilter(
            Arrays.asList("a", "abc", "abcdef", "ab"),
            3
        );
        System.out.println(filtered);  // [abc, abcdef]

        // Static method
        String formatted = DataProcessor.format(
            "Hello {{name}}, you are {{age}} years old",
            Map.of("name", "Alice", "age", 30)
        );
        System.out.println(formatted);
    }
}

Groovy Default Parameters from Java

Groovy default parameters are not visible from Java directly:

// Config.groovy
class Config {
    String getGreeting(String name, String prefix = "Hello") {
        "$prefix, $name!"
    }
}
// Java must supply all parameters
Config cfg = new Config();
// String result = cfg.getGreeting("Alice");  // ERROR
String result = cfg.getGreeting("Alice", "Hello");  // OK

Use method overloading for Java-friendly APIs.

Groovy Closure from Java

// Transformer.groovy
class Transformer {
    List<String> transform(List<String> items, Closure<String> fn) {
        items.collect(fn)
    }
}
// Java calling Groovy with closure
import groovy.lang.Closure;

Transformer t = new Transformer();

Closure<String> upperCaseClosure = new Closure<String>(null) {
    String doCall(String it) {
        return it.toUpperCase();
    }
};

List<String> result = t.transform(Arrays.asList("a", "b", "c"), upperCaseClosure);
System.out.println(result);  // [A, B, C]

Gradle Multi-Language Build

// build.gradle
plugins {
    id 'java'
    id 'groovy'
}

repositories {
    mavenCentral()
}

sourceSets {
    main {
        java { srcDirs = ['src/main/java'] }
        groovy { srcDirs = ['src/main/groovy'] }
    }
    test {
        groovy { srcDirs = ['src/test/groovy'] }
    }
}

dependencies {
    implementation 'org.codehaus.groovy:groovy-all:4.0.15'
    testImplementation 'org.spockframework:spock-core:2.3-groovy-4.0'
}

Groovy and Java code coexist in the same project.

@CompileStatic for Java Compatibility

import groovy.transform.CompileStatic

@CompileStatic
class JavaFriendly {
    String greet(String name) {
        "Hello, $name"
    }

    int add(int a, int b) {
        a + b
    }
}

Without @CompileStatic, method signatures remain the same but method bodies use Groovy's dynamic dispatch.

GroovyBean Property Access

// Person.groovy
@Canonical
class Person {
    String firstName
    String lastName
    int age
}
Person p = new Person("Alice", "Smith", 30);
// Java sees: getFirstName(), setFirstName(), getLastName(), etc.
System.out.println(p.getFirstName());  // Alice
System.out.println(p.getAge());        // 30

Common Mistakes

1. Assuming Groovy's == works the same from Java

Groovy's == calls equals. Java's == compares references. When calling Groovy code from Java, use .equals().

2. Forgetting Groovy runtime jar

Groovy classes need groovy-all.jar on the runtime classpath, even if the Groovy code uses @CompileStatic.

3. Default parameters invisible from Java

Groovy default parameters are not overloads. Java callers must pass all arguments.

4. Closure parameter type inference loss

Java callers must provide explicit type parameters for closures passed to Groovy.

5. Mixed project build order

In Gradle, Groovy compilation depends on Java compilation (or vice versa) depending on the dependsOn configuration.

Practice Questions

1. What is required to use Groovy classes from Java?

The groovy-all.jar (or specific Groovy JARs) on the classpath at runtime.

2. How does @CompileStatic affect Java callers?

It makes method dispatch direct (like Java), improving performance. Method signatures remain the same.

3. Can Java call Groovy closure parameters?

Yes, by creating groovy.lang.Closure instances in Java code.

4. How do GroovyBean properties appear to Java?

As standard JavaBean getter/setter methods following the property naming convention.

Challenge: Create a mixed Java/Groovy project where Groovy handles data transformation and Java handles I/O.

FAQ

{{< faq question="Does Groovy compile to the same bytecode as Java?" >}} Similar but not identical. Groovy bytecode includes metaclass hooks and call site Caching that Java bytecode does not. {{< /faq >}}

{{< faq question="Can Java extend a Groovy class?" >}} Yes. Java classes can extend Groovy classes and call super methods normally. {{< /faq >}}

{{< faq question="Can Groovy implement a Java interface?" >}} Yes. Groovy classes can implement Java interfaces, including with dynamic method resolution via methodMissing. {{< /faq >}}

{{< faq question="What is the performance impact of calling Groovy from Java?" >}} Minimal with @CompileStatic. Without it, dynamic dispatch is ~2-5x slower than pure Java. {{< /faq >}}

{{< faq question="Can I decompile Groovy bytecode to Java?" >}} Yes, but the decompiled code is verbose due to Groovy's runtime support classes. Tools like CFR and Procyon work. {{< /faq >}}

Mini Project

Create a Groovy class that processes CSV data and a Java main class that uses it.

// CsvProcessor.groovy
import groovy.transform.CompileStatic

@CompileStatic
class CsvProcessor {
    List<Map<String, String>> parse(String csvContent) {
        def lines = csvContent.readLines()
        if (lines.isEmpty()) return []
        def headers = lines[0].split(',') as List<String>
        return lines.drop(1).collect { line ->
            def values = line.split(',') as List<String>
            [headers, values].transpose().collectEntries { [(it[0]): it[1]] }
        }
    }
}
// Main.java
public class Main {
    public static void main(String[] args) {
        CsvProcessor proc = new CsvProcessor();
        String csv = "name,age\nAlice,30\nBob,25";
        List<Map<String, String>> data = proc.parse(csv);
        data.forEach(row ->
            System.out.println(row.get("name") + " is " + row.get("age"))
        );
    }
}

What's Next

Now that you understand Groovy classes from Java, proceed to the Groovy ecosystem overview.

Topic Description Link
Ecosystem Groovy tools and frameworks {{< ref "30-ecosystem" >}}
Gradle Build integration {{< ref "17-gradle-integration" >}}
Java Comparison with Java Java

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro