Groovy и Java — совместимость и отличия
Groovy и Java — совместимость и отличия
Groovy компилируется в байт-код JVM и использует те же классы из JDK и Maven-зависимостей. На практике его часто описывают как «Java с синтаксическим сахаром», но это упрощение: есть отличия, которые ломают ожидания при переносе кода и при вызове из Java.
Что обычно работает без изменений
Большая часть валидного Java 8+ кода компилируется groovyc как Groovy:
- объявления классов, интерфейсов, enum (с оговорками по новым фичам Java);
- поля, методы, наследование, generics в исходниках;
- вызовы JDK (
java.util,java.time, NIO, JDBC и т.д.); - аннотации Java и многие библиотеки Spring, Hibernate, JUnit.
// Фрагмент «чистой» Java внутри .groovy-файла
import java.util.stream.Collectors
List<String> names = List.of("a", "b", "c")
List<String> upper = names.stream()
.map(String::toUpperCase)
.collect(Collectors.toList())
Обратное направление: Java-класс вызывается из Groovy напрямую, без обёрток.
Главные отличия (ловушки при переходе)
| Тема | Java | Groovy |
|---|---|---|
== | Сравнение ссылок (для объектов) | Вызов equals() |
| Идентичность | == для примитивов | is() или === (версия Groovy) |
| Деление int | 5 / 2 → 2 | 5 / 2 → 2.5 |
| Строки | Только String | String и GString ("Hi $name") |
| Тип переменной | Обязателен (кроме var с Java 10+) | def — вывод типа |
| Итерация | for, Stream | for (x in list), each, collect |
| Проверка «пусто» | Явные сравнения | Truthiness: if (list) |
| Исключения | Проверяемые throws | Не проверяются компилятором Groovy |
| Скрипт | Нужен class + main | Топ-уровневые выражения в .groovy |
GString и сравнение
def plain = 'Hello'
def gstr = "Hello"
assert plain == gstr // true — equals по содержимому
assert !plain.is(gstr) // false — разные классы
В Java == для двух new String("Hello") дало бы false (ссылки).
Операторы, которых нет в Java
?.— безопасная навигация;?:— Elvis (значение по умолчанию для «ложного» операнда);*.method()— spread по коллекции;in/!in— принадлежность;=~/==~— регулярные выражения;../..<— диапазоны.
Ключевые слова только в Groovy
def, as, trait, in, it (неявный параметр замыкания), словесные and / or / not и др. — см. ключевые слова.
Вызов Groovy из Java
Работает предсказуемо, если Groovy-класс ведёт себя как обычный JavaBeans-класс:
- явные типы в публичных методах;
- без опоры на
methodMissing/ динамические свойства в API, видимом Java; - рантайм Groovy (
groovy-*.jar) в classpath при необходимости.
// Java
Person person = new Person("Alice", 30);
System.out.println(person.getName());
// Groovy — компилируется в .class с getName()/setName()
class Person {
String name
int age
Person(String name, int age) {
this.name = name
this.age = age
}
}
Сложнее из Java:
- скрипты без класса (нужен
GroovyShell/GroovyClassLoader); - DSL с
methodMissing, категории, глобальныйmetaClass; - методы только с
defв сигнатуре на границе API.
Для публичного API библиотек предпочтительны явные типы и @CompileStatic на границе модулей.
Динамика vs статика в одном проекте
| Режим | Когда | Поведение |
|---|---|---|
| По умолчанию | Скрипты, Gradle, Spock | MetaClass, позднее связывание |
@TypeChecked | Поиск ошибок типов | Проверка при компиляции, вызовы могут оставаться динамическими |
@CompileStatic | Ядро, hot path | Вызовы как в Java, меньше рантайма Groovy |
Типичная схема в enterprise: Java или @CompileStatic Groovy для домена, динамический Groovy для сборки, пайплайнов и тестовых спецификаций.
Что не стоит утверждать в документации и на собеседованиях
- «Любой Java-код — валидный Groovy» — неверно для edge cases и новых конструкций только в Java.
- «100% бинарная совместимость» — на практике совместимость высокая, но динамические фичи и различия операторов требуют внимания.
- «Groovy заменил Java в вебе» — Grails уступил долю Spring Boot; Groovy остался в инфраструктуре.
Связанные материалы
- Типы данных —
def, GString, коллекции - Операторы —
==, Elvis, диапазоны - Основы языка — MetaClass, компиляция
- Рекомендации по разработке — стиль и
@CompileStatic
См. также
Другие статьи этого же раздела в боковом меню (как на странице «О разделе»). Краткая хронология Groovy на JVM — от идеи James Strachan до ниши Gradle, Jenkins и Spock. Фундамент для начинающего программиста - что повторить, как работать, чего ожидать. Набор советов, правил, принципов и обычаев в разработке на этом языке. Макросы на уровне языка (начиная с Groovy 2.5) — groovy.transform.Macro позволяет инжектить код, основываясь на анализе AST. Статическая и динамическая типизация в Groovy, примитивы JVM, строки GString, коллекции, диапазоны и ключевые операторы def, as, instanceof. Операторы и выражения в Groovy - арифметика, логика и выразительный синтаксис поверх JVM-экосистемы. Циклы и управляющие конструкции Groovy - императивные и декларативные способы описания логики выполнения. В этом примере greet — это переменная, содержащая замыкание. Замыкание принимает один параметр name и выводит приветствие. Вызов greet(Groovy) выполняет код внутри замыкания. Нет проверяемых исключений — компилятор Groovy игнорирует механизм throws, принятый в Java. Динамическая типизация, метапрограммирование, AST-трансформации, DSL, работа с XML и JSON, синтаксический сахар и интеграция с Java. Кавычки, скобки, замыкания, switch, регулярные выражения и truthiness в Groovy. Groovy использует все ключевые слова Java и добавляет собственные для упрощения синтаксиса. Справочник разделён на логические группы для удобства использования.История языка Groovy
Что требуется знать перед началом изучения языка программирования Groovy
Рекомендации по разработке на Groovy
Основы языка Groovy
Типы данных и объявление переменных
Операторы и выражения в Groovy
Циклы и управляющие конструкции
Объектно-ориентированное программирование в Groovy
Иерархия исключений в Groovy
Особенности и расширения языка Groovy
Синтаксис и пунктуация в Groovy
Ключевые слова языка Groovy