java что такое groovy
Groovy за 15 минут – краткий обзор
Groovy — объектно-ориентированный язык программирования разработанный для платформы Java как альтернатива языку Java с возможностями Python, Ruby и Smalltalk.
Groovy использует Java-подобный синтаксис с динамической компиляцией в JVM байт-код и напрямую работает с другим Java кодом и библиотеками. Язык может использоваться в любом Java проекте или как скриптовый язык.
Возможности Groovy (отличающие его от Java):
— Статическая и динамическая типизация
— Встроенный синтаксис для списков, ассоциативных массивов, массивов и регулярных выражений
— Замыкания
— Перегрузка операций
Более того, почти всегда java-код — это валидный groovy-код.
Установка
В IDE NetBeans 7.0 поддержка groovy идет из коробки, для IDE Eclipse существует очень хороший плагин, который можно взять здесь.
Groovy
Самое главное отличие от java: в Groovy всё является объектами. Все примитивные типы сразу же упаковываются в объекты. Т.е. «int x» на самом деле является «Integer x»
Следует не забывать о том, что все упаковочные типы — неизменяемые, поэтому каждый раз при каком-либо вычислении будет создаваться новый объект.
Строки в Groovy
1) Java Strings — строки в одинарных кавычках
2) Groovy Strings, они же GStrings — в обычных кавычках
В строках groovy можно вставлять параметры, в обычные строки — нельзя
К строкам применимы операции + и *
В groovy есть поодержка регулярных выражений на уровне конструкций языка:
Встроенная поддержка maps + lists
Так же на уровне конструкций языка поддерживаются словари (maps) и списки:
Ranges
Получать доступ к элементам списков в groovy можно следующим образом:
Range — это такой же объект, поэтому возможны конструции, подобные последней. Отрицательные индексы, как в python, возвращают элементы с конца списка.
Range можно составить из строк:
Более того, range можно сделать из любого объекта, у которого есть методы next() и prev().
Циклы
Циклы в groovy точно такие же, как и в java, плюс к ним добавляется еще один «foreach»:
Функции
Ключевое слово return указывать не обязательно — по умолчанию будет возвращено значение последней упомянутой переменной в фукции.
Closures
Closure — это анонимная функция
У многих объектов есть методы, в качестве параметров которым передаются closure:
Доступно большое количество методов для обработки последовательностей, к которым можно применять замыкания:
В closure так же не обязательно использовать ключевое слово return. Если явно не задано имя параметру, то по умолчанию используется it.
Так как closure является объектом, то ничего не мешает возвращать его из другого closure, и таким образом создавать функции высших порядков:
Файлы
Для директорий есть функции eachFile и eachFileRecursive:
Для обработки текстовых файлов — функция eachLine:
Писать в файлы так же очень удобно:
Классы
Неизменяемые классы задаются с помощью аннотации Immutable:
При использовании этой аннотации нужно явно указывать, какого типа данных поле.
Операторы
Проверяет переменную a, и если в ней null или false, то берет указанное следом значение. Иначе берется значение переменной a.
«?.» Safe navigation
Используется для избежания ошибки NullPointerException
Вернет null, если если в user содержится null вместо того, чтобы бросать NullPointerException.
«*.» Spread operator
Применяет указанный метод для всех элементов какой-либо коллекции. Эквивалент следующему:
Так же монжо использовать для составления списков и словарей:
Оператор «==» уже перегружен для всех объектов — и вызывает метод «isEquals()». Полный список методов, которые нужно переопределить для перегрузки операторов, доступен здесь: http://groovy.codehaus.org/Operator+Overloading.
SQL запросы обрабатываются очень просто:
В groovy существуют билдеры, которые можно использовать для генерации XML. Для генерации создается экземпляр объекта MarkupBuilder, на котором вызываются псевдо-методы — название этого метода и переданные параметры будет использоваться для генерации тега:
В качестве параметра конструктору MarkupBuilder можно передавать любой PrintWriter:
Парсинг XML так же очень простой:
Groovlets
С помощью класса GroovyServlet возможно запускать скрипты на Groovy как сервлеты.
В первую очередь, для этого нужно добавить несколько строчек в web.xml:
— request & response
— context, application, session
— out (= response.getWriter())
— sout (= response.getOutputStream())
— html (= new MarkupBuilder(out))
Отдаст браузеру сгенерированную html-страницу.
Apache NetBeans 12.5
Этот документ используется для начала работы с Groovy в IDE NetBeans. В процессе работы будет создано приложение на языке Java, добавлен элемент JFrame, а из файла Groovy будет получено простое сообщение.
Для работы с этим учебным курсом требуется следующее программное обеспечение и ресурсы.
пакет Java, версии 7.2, 7.3, 7.4, 8.0
Подключаемый модуль Groovy
Активация подключаемого модуля Groovy
Поддержка Groovy отключена по умолчанию при установке Java-версии среды IDE. Для работы с Groovy в IDE сначала необходимо активировать подключаемый модуль Groovy в диспетчере подключаемых модулей.
Выберите ‘Сервис’ > ‘Подключаемые модули’ в главном меню, чтобы открыть диспетчер подключаемых модулей.
Перейдите на вкладку Установлено в диспетчере подключаемых модулей.
Выберите ‘Показать сведения’ и найдите подключаемый модуль Groovy и Grails в списке подключаемых модулей.
В качестве альтернативы вы можете ввести groovy в поле поиска, чтобы отфильтровать список подключаемых модулей.
Установите подключаемый модуль ‘Groovy and Grails’ и нажмите ‘Активировать’.
Нажмите кнопку ‘Активировать’ в окне ‘Мастер установки NetBeans IDE’, чтобы активировать подключаемый модуль Groovy.
Нажмите кнопку ‘Завершить’ в окне ‘Мастер установки NetBeans IDE’ после завершения установки и затем нажмите ‘Закрыть’ в диспетчере подключаемых модулей.
Создание приложения
В этом разделе вы узнаете, как создать новое приложение Java.
Выберите ‘Файл > Создать проект’ (Ctrl-Shift-N; ⌘-Shift-N в Mac) в главном меню, чтобы открыть мастер создания проектов.
В категории Java выберите ‘Приложение Java’. Нажмите кнопку «Далее».
В поле ‘Имя проекта’ введите GroovyJavaDemo, а в поле ‘Местоположение проекта’ укажите папку, где будет создано приложение.
Снимите флажок «Создать главный класс». Нажмите кнопку «Готово».
При нажатии на кнопку ‘Готово’ IDE создает проект, который отображается в окне ‘Проекты’.
Создание класса Java и файла Groovy
В этом разделе вы узнаете, как создать элемент JFrame и класс Groovy.
Щелкните правой кнопкой мыши узел проекта в окне ‘Проекты’ и выберите ‘Создать > Другое’. Откроется диалоговое окно мастера создания файлов.
В категории ‘Формы Swing GUI’ выберите ‘Форма JFrame’. Нажмите ‘Далее’.
В поле ‘Имя класса’ введите DisplayJFrame.
В поле ‘Пакет’ введите org.demo. Нажмите ‘Готово’.
При нажатии на кнопку ‘Готово’ в среде IDE создается форма JFrame, и в редакторе открывается соответствующий файл.
Щелкните правой кнопкой мыши узел проекта в окне ‘Проекты’ и выберите ‘Создать > Другое’. Откроется диалоговое окно мастера создания файлов.
В категории Groovy выберите ‘Класс Groovy’. Нажмите ‘Далее’.
В поле ‘Имя класса’ введите GreetingProvider.
При нажатии на кнопку ‘Готово’ IDE создает файл Groovy и открывает его в редакторе.
Если развернуть узел проекта в окне ‘Проекты’, можно увидеть два только что созданных файла под узлом ‘Исходные пакеты’.
Вызов файла Groovy из класса Java
В этом разделе вы узнаете, как создать код для взаимодействия между файлом Groovy и классом Java.
Откройте файл GreetingProvider.groovy в редакторе (если он еще не открыт).
Задайте переменную приветствия в определении класса, добавив следующий код (выделен полужирным шрифтом). Сохраните изменения.
Откройте файл DisplayJFrame.java в редакторе (если он еще не открыт) и перейдите на вкладку ‘Конструирование’.
Откройте палитру (выберите ‘Окно > Палитра’ в главном меню) и перетащите элемент ‘Текстовое поле’ ( jTextField ) и палитры на форму JFrame.
Перейдите на вкладку ‘Исходный код’ и добавьте следующий исходный код в верхнюю часть тела класса, чтобы создать экземпляр класса Groovy и вызвать метод getGreeting() в классе Groovy в конструкторе.
Для поиска в классе Java методов, необходимых для класса Groovy, можно использовать автозавершение кода.
Щелкните правой кнопкой мыши узел проекта в окне «Проекты» и выберите «Выполнить».
Если выбрать команду ‘Выполнить’, IDE выполнит сборку и запуск приложения.
В текстовом поле в окне приложения отображается текст из класса Groovy.
Теперь читатель может создать базовое приложение на языке Java, взаимодействующее с Groovy.
Дополнительные сведения
IDE NetBeans также поддерживает веб-платформу Grails, в которой используется язык Groovy при веб-разработках на Java. Дополнительные сведения об использовании платформы Grails с IDE NetBeans см. в разделе Введение в платформу Grails.
Groovy как скриптовый язык и DSL для Java
Зачем?
При разработке разного рода ПО, например, задач мониторинга или обслуживания, я сталкиваюсь с необходимостью поддержки в программе выполнения сценариев, описывающих или выполняющих некоторый набор действий. И специфика такова, что добавление или изменение таких сценариев в ПО не должно требовать пересборки или перезапуска ПО.
Наверное, самыми простыми примерами таких сценариев, с которыми все сталкивались в том или ином виде, могут служить обычные пакетные файлы — bat или sh.
В своей практике, я иногда использую XML для описания сценариев. В случае, четко определенного заранее набора действий и их простого плоского набора без ветвлений — XML не плох для использования. Тут и фиксированная структура, позволяющая валидировать файл сценария, и простота самого языка XML, позволяющая с ним работать не только программистам. Однако реализовывать ветвления или условную логику в XML, на мой взгляд, очень накладно и сродни написанию своего мини языка. Расширение набора действий чаще всего возможно только при изменении исходного кода программы, да и изначально реализация поддержки XML сценария трудозатратна.
В общем, в поисках более простого и функционального инструмента, для описания сценариев, взор был обращен к скриптовым языкам. Так как платформа Java, то хотелось иметь возможности интеграции скриптового языка и Java. В итоге, выбор пал на Groovy – динамический язык на базе JVM, легко интегрируемый с Java, простой и выразительный, имеющий много полезных возможностей для нашей задачи.
Скрипты
Я не буду рассказывать основы Groovy, так как материалов в сети даже на русском уже предостаточно. Остановлюсь лишь на некоторых ключевых для нас моментах.
Groovy позволяет нам из Java кода выполнять не скомпилированный исходный Groovy код, что позволяет нам выполнять сценарии добавленные или измененные в runtime.
Рассмотрим пример выполнения Groovy скрипта в Java. Для поддержки Groovy в Вашем Java проекте нужно подключить в зависимости лишь одну библиотеку «groovy» нужной Вам версии.
Напишем следующий Groovy код в файле x:\GroovyScript.groovy:
Код для выполнения данного скрипта в Вашем Java код может быть таким:
В итоге выполнения, в консоль выведется 2 строки, первая из скрипта, вторая — из Java, с результатом выполнения скрипта:
Groovy script
result=16
Пример не несет функциональной нагрузки в скрипте, однако показывает возможности динамической загрузки и выполнения – всего две строчки кода и мы получаем возможность выполнения скриптов.
Немного о Java коде. GroovyShell – это класс предоставляемый Groovy для выполнения groovy скриптов. Существуют и другие способы выполнения groovy скриптов, подробнее смотрите тут
DSL – domain-specific language или предметно ориентированный язык. Язык, позволяющий использовать основные операции предметной области через набор простых и понятных высокоуровневых функций, скрывающий от пользователя их реализацию.
В приведенном выше примере код достаточно простой, однако в реальном сценарии он может быть очень большим и сложным. И работать с такими скриптами смогут только groovy-разработчики, избежать ошибок без тестирования будет сложно. В случае заранее известных операций в сценариях, всю бизнес логику можно вынести в код (java или groovy — неважно), и предоставить возможность использовать ее через набор функций.
Рассмотрим небольшой пример. Требуется написать скрипт, который будет выполнять архиваций, распаковку архивов, удаление, некоторые проверки и уведомления.
Один их кусочков сценария мог бы быть таким – проверить состояние процесса и в случае его завершения заархивировать каталог и послать уведомление:
//import
…
//check state
Process p = getProcess ( … )
int state = p. getCompleteState ( … )
if ( state == 1 ) <
//doSomeLogicForArchive
Zip z = new Zip ( … )
z. makeZip ( … )
> else <
//doAnotherLogic
return
>
//doSomeLogicForSendNotify
Smtp smtp = new Smtp ( … )
Message m = new Message ( … )
smtp. send ( to,m. )
Код получается достаточно большим, и он будет понятен, в основном, лишь программистам. Давайте его упростим и вынесем три указанных действия в класс ArchiveScript со статическими методами. Скрипт после вынесения методов:
Уже лучше? — Лучше, но все еще есть артефакты – импорт и названия класса, которые тоже стоило бы убрать. И в Groovy есть подобная возможность – возможность задания базового класса для скрипта вне самого скрипта. Класс ArchiveScript для этого должен наследоваться от Script и методы могут быть не статическими. Код скрипта при этом еще упрощается – исчезает импорт и префикс класса:
Уже достаточно хорошо. В случае если код внутри блока ветвления условия однострочный, можно отказаться и от фигурных скобок. А в случае Groovy часто и от скобок справа от имени метода. Код выполнения скрипта немного усложняется — нужно создать объект CompilerConfiguration, установить значение scriptBaseClass равное имени созданного нами класса ArchiveScript и передать этот объект в GroovyShell:
CompilerConfiguration conf = new CompilerConfiguration ( ) ;
conf. setScriptBaseClass ( «package.ArchiveScript» ) ;
GroovyShell shell = new GroovyShell ( conf ) ;
Далее, давайте рассмотрим, как задаются параметры методов в скрипте при вызове. В случае определения в классе ArchiveScript метода makeArchive в таком виде:
def makeArchive ( sourcePath, destPath, deleteSource )
В скрипте вызов должен был бы выглядеть так:
И если говорить о наглядности и даже удобстве Groovy позволяет нам сделать передачу параметров через именованные параметры, так:
Однако в этом случае параметры будут передаваться внутри HashMap и, соответственно, получение параметров в makeArchive в классе ArchiveScript должно быть таким:
Если применить преобразование и для других вызовов, то в конечном итоге наш скрипт мог бы выглядеть так:
И это уже не слишком сложный и достаточно читаемый код.
Таким образом, мы получили свой мини-DSL с несколькими предопределенными функциями, специфичными для нашей задачи. А также все еще имеем возможность использовать всю мощь исходного языка.
Замечу, что я рассмотрел лишь малую толику разработки DSL. В Groovy есть более широкая поддержка разработки своего DSL, а так же DSL-поддержка для Eclipse и для IntelliJ Idea
Тестирование
Хотелось бы сказать несколько слов о тестировании сценариев. Каким бы простым не был скрипт, ошибки могут быть и в нем. Даже если Вы пишите сценарии в IDE, полноценной проверки на корректность синтаксиса Вы можете не получить. Это возможно лишь при его выполнении. Так же необходимо проверять поведение скрипта.
Так как нам не хотелось бы выполнять реальные действия при выполнении тестирования сценария, то нужно каким-то образом заменить реальную логику на имитацию. Groovy позволяет нам это сделать многими путями. Покажу несколько из них.
Замена базового скрипта
Создаем новый класс ArchiveSciptMock который имеет интерфейс аналогичный ArchiveScript, и реализующий нужное нам поведение (или ничего не делающий). При создании объекта конфигурации CompilerConfiguration передаем его имя вместо оригинала.
CompilerConfiguration conf = new CompilerConfiguration ( ) ;
conf. setScriptBaseClass ( «package.ArchiveScriptMock» ) ;
Замена методов в базовом классе скрипта
Другим вариантом без создания дополнительного mock класса может быть замена методов на mock в самом ArchiveScript. В groovy это можно сделать, например, таким способом:
Недостатком и первого и второго способа я бы считал необходимость написания дублирующей логики по проверки правильности передаваемых параметров. Так как если в ArchiveScriptMock метод makeArchive будет таким:
def makeArchive ( params ) <
//makeArchiveInternal params.sourcePath, params.destPath, params.deleteSource
>
То мы не проверим все ли параметры были переданы. Нужно будет писать что-то похожее на это:
Я бы предложил сделать небольшой рефакторинг ArchiveScript — сделать ArchiveScript фасадом и всю логику перенести в другой класс. Например, в Java класс Archive.
Рефакторинг — не только для целей тестирования, но и из других соображений, например, для отделения поведения от способа выполнения (нет зависимости от Script). В итоге, после изменения, ArchiveScript примет такой вид:
Теперь, можно тестировать логику и сценарий в отдельности. Заменим Archive на его mock и выполним скрипт:
Естественно поведение Archive можно заменить и с помощью java mock фреймворков, однако, нам пока достаточно и этого.
Я считаю, что получил достаточно гибкий инструмент для написания сценариев, без недостатков, озвученных в начале текста, а также достаточно простотой в использовании. Контроль корректности сценария так же не был потерян — использование mock поведения позволяет нам тестировать их в достаточной мере, перед реальным выполнением.
Проект с исходными кодами проекта — groovydsl. Компилируется Gradle через враппер.
Некоторые идеи взяты из книги Groovy for Domain-Specific Languiages, Fergal Dearle, 2010
Groovy как лучшая Java
Groovy можно использовать по разному — для скриптов, для Grails, для быстрого написания прототипов, для DSL и т.д.
Меня же Groovy всегда привлекал как улучшенная Java. В самом деле — почти любой Java код будет валидным кодом Groovy — т.е. если не помнишь как что то делать в Groovy-way, можно всегда писать так, как принято в Java, а если помнишь — вот тебе и Closures, и удобные списки, и много других замечательных вещей.
Единственное, что мешало использовать Groovy для разработки production кода — отсутствие ошибок компиляции в большом числе случаев. Например если вызываешь несуществующий метод, обращаешься к несуществующей переменной и т.д.
Для многих Groovy фреймворков и библиотек это реально нужно (см. например работу с XML в Groovy), но если я пишу обычный код, мне это серьезно мешает.
Так вот, наконец в Groovy 2.0 появилась возможность сказать — проверяй в этом классе типы, существование методов и переменных!
Возьмем, например, такой класс:
Он комплируется без проблем.
Но если мы добавим
@TypeChecked (эта аннотация может быть на классе или методе), то получим ошибки:
Также проверка автоматически включается, если мы включаем для класса статическую компиляцию аннотацией @CompileStatic :
Теперь можно будет писать на Groovy всё то, что писалось на Java и не бояться проблем, пропущенных компилятором.
Полный список проверок можно найти здесь.
Было бы еще классно, если бы сделали проверку типов по умолчанию, а динамическую типизацию по аннотации…
Groovy
Данный учебник представляет из себя руководство по языку программирования Groovy
Содержание
Установка и настройка [ править ]
На странице загрузки выбираем удобный способ установки (предварительно установив Java (JDK)). После установки могут быть доступны Groovy Console и Groovy Shell в которых можно набирать код и запускать его.
Также запустить код можно прямо из Groovy Web Console.
Перед запуском проверьте чтобы в путях Вашей ОС были прописаны переменная GROOVY_HOME и путь в переменной PATH к исполняему файлу groovy.bat (или groovy.sh)
Также файл с кодом можно выполнить через Java. Делается это так:
Первая программа [ править ]
Откройте редактор и напишите программу. По традиции, первая программа должна просто выводить приветствие миру:
Сохраните её в файл helloworld.groovy и запустите.
На экране появится надпись:
На этом традиционную часть можно считать выполненной.
Комментарии и демонстрация результата [ править ]
Комментарием называется часть программного кода, пропускаемая при обработке (интерпретации или компиляции).
Переменные [ править ]
Переменная, которая может иметь неопределенное значение на этапе компиляции или надо скрыть этот тип, в Groovy определяется ключевым словом def (аналогично var в Java):
Строки [ править ]
В Groovy есть 2 типа строк:
Списки [ править ]
Groovy содержит встроенную поддержку списков. Списки объявляются путем перечисления элементов в квадратных скобках:
Обращение к элементам списка осуществляется по индексу, как к массиву в Java:
Новые элементы могут быть добавлены в список различными способами:
Теперь, совместное использование списков и ranges:
Также, для индексирования можно использовать и списки:
Также, Groovy предоставляет встроенный цикл, для перебора элементов списка, или элементов любого объекта, реализующего интерфейс java.lang.Iterable:
Map (Ассоциативный массив) [ править ]
Аналогично обычным массивам (спискам), Groovy поддерживает прозрачный синтаксис для работы с maps (ассоциативными массивами). Объявление выглядит следующим образом:
Также, существует специальный синтаксис для объявления пустых map:
Доступ к элементам осуществляется по ключу, с использованием оператора [], или же с ключом как полем:
Аналогично производится и изменение элементов:
Для хранения объектов в качестве ключа можно использовать скобки ():
Условное исполнение [ править ]
Одной из наиболее важных особенностей любого языка программирования является возможность выполнять различные коды в разных условиях. Простейший способ сделать это состоит в использовании IF конструкции. Например:
Не беспокойтесь о длинной первой строке, это просто какой-то код, чтобы определить, сейчас утро или вечер. Остальная часть кода выполняется следующим образом: сначала оценивается выражение в круглых скобках и в зависимости от результата true (истинно) или false (ложно) выполняется первый или второй блок кода. Смотрите ниже раздел логические выражения.
Обратите внимание, что блок else не требуется, в отличие от первого блока:
Логические выражения [ править ]
Более сложные логические выражения используют один из булевых операторов:
Функции и методы всегда возвращают, как результат, последнее выражение.
Closures (Замыкания) [ править ]
Синтаксис замыкания : < [closureArguments->] statements >
В замыканиях по умолчанию присутствует переменная it и ссылается на первый параметр в замыкании:
Определение замыкания в классе и его вызов:
Если нужно передать замыкание в метод принимающий интерфейс(например функциональный), то делают так:
Специальный класс Expando для создания динамических объектов и методов (как замыкания) которые можно вызывать:
Работа с файлами [ править ]
Работа со строками [ править ]
Classes and Objects (Классы и объекты) [ править ]
Описание и создание класса(по умолчанию класс имеет тип доступа public, а переменные класса имеют тип доступа private, но компилятор groovy сам сделает для этих полей геттеры и сеттеры с доступом public):
Groovy добавляет к обычному классу конструктор принимающий один аргумент типа Map если не определен другой конструктор.
С помощью аннотации @MapConstrutor мы можем добавить к классу конструктор с параметром Map:










