Groovy 4.0:それを素晴らしい10の新機能!


最新のGroovy 4.0は多くの興味深い特徴を紹介した.閉じるこの動画はお気に入りから削除されています.

公開


特徴和1:スイッチ式


GroovyはJavaに比べてずっと強力なスイッチ文を持ちました.クラスケース値、正規表現ケース値、コレクションケース値、クロージャケース値、または末尾、等しい値の場合.すべてのこれらのオプションは、スイッチ声明をグルーヴィーな世界で一流の市民にしました.そして今、Javaプログラミング言語の最新の更新に続いて、Groovyもスイッチ式をサポートします.switch文とswitch式の主な違いは、後者がJavaと互換性のある構文を導入し、値を返すことです.あなたはまだケースとして様々な組み合わせを使用することができます、しかし、新しい構文はあなたのコードをもう少しエレガントにします.
switch (value) {
    case null -> 'just a null'
    case 0 -> 'zero'
    case 1 -> 'one'
    case { it instanceof List && it.empty } -> 'an empty list'
    case List -> 'a list'
    case '007' -> 'James Bond'
    case ~/\d+/ -> 'a number'
    default -> 'unknown'
}

特徴音2:記録


記録は、便利な不変の“データキャリア”タイプは、Java 16で導入されました.現在、Groovyでも利用できます.Groovyも紹介しますが、同じ構文@RecordType あなたが交換可能に使用できる注釈.そして、たとえそれがJavaのためのゲームチェンジャーでないとしても、Groovyがその母国語で紹介された最新機能で立ち向かうのを見るのは良いです.
record Point(int x, int y) {}

def p1 = new Point(0, 0)
def p2 = new Point(2, 4)
def p3 = new Point(0, 0)

assert p1.x() == 0
assert p1.y() == 0
assert p2.x() == 2
assert p2.y() == 4
assert p1.toString() == 'Point[x=0, y=0]'
assert p2.toString() == 'Point[x=2, y=4]'
assert p1 == p3

特徴懸三:密封型


Javaプログラミング言語の最新の変化の影響を受けたもう一つの特徴.密封されたタイプで、どのクラス(またはインターフェース)が特定の密封タイプを広げることができるかを制限することができます.すべての関連するクラスが同じソースファイルに格納されている場合は、明示的に(“許可”キーワードを使用)、または暗黙のうちに(任意のキーワードなし)行うことができます.レコードと同様に、Groovyも@Sealed これがあなたの好みであるならば、あなたが交換可能に使うことができる注釈.密封型を使用する場合は?たぶん、誰もがセキュリティ上の理由でクラスを拡張できるようにしたくない.あるいは将来のインターフェイスに新しいメソッドを追加したり、影響を受けたサブクラスを厳密に制御したりする必要があります.それがケースであるならば、封をされたタイプはあなたが見たい何かであるかもしれません.
import groovy.transform.ToString

sealed interface Tree<T> { }

@Singleton
final class Empty implements Tree {
    String toString() { "Empty" }
}

@ToString
final class Node<T> implements Tree<T> {
    final T value
    final Tree<T> left, right

    Node(T value, Tree<T> left, Tree<T> right) {
        this.value = value
        this.left = left
        this.right = right
    }
}

タイプチェックイン4:タイプチェッカー


Groovyは主にダイナミックな機能で知られていますが、Javaよりもタイプチェックにおいて、より厳密にすることができます.新たに追加groovy-typecheckers オプションのモジュールでは、コンパイル時に正規表現のエラーをキャッチできる正規表現チェッカーを紹介します.この例のように、閉じた括弧がない正規表現があります.通常、コンパイラはこの種の問題を検出できません.したがって、単体テストまたはランタイムでそれを見つけます.ここでは、このスクリプトをgroovyshellで実行します.
import groovy.transform.TypeChecked

@TypeChecked(extensions = 'groovy.typecheckers.RegexChecker')
def testRegexChecker() {
    def date = '2022-04-03'

    assert date ==~ /(\d{4})-(\d{1,2})-(\d{1,2}/
}

マクロ単位でのメソッド


マクロメソッドを使用すると、コンパイラASTデータ構造体にアクセスおよび操作できます.マクロメソッドコールは通常のメソッド呼び出しに似ていますが、コンパイル時に生成されたコードに置き換えられます.マクロメソッドの例をいくつか示します.例えば、SV メソッドは変数名と関連する値を持つ文字列を作成します.The SVI 一つはGroovyの検査メソッドを使用します.このメソッドは、たとえば、この例で示すように、さまざまな出力を生成します.
def num = 42
def list = [1 ,2, 3]
def range = 0..5
def string = 'foo'

assert SV(num, list, range, string) == 'num=42, list=[1, 2, 3], range=[0, 1, 2, 3, 4, 5], string=foo'

assert SVI(range) == 'range=0..5'

assert NV(range) instanceof NamedValue

assert NV(string).name == 'string' && NV(string).val == 'foo'

特徴の残忍6


Groovyに精通しているなら、すべてのGroovyクラスがGroovyObject インターフェイス.あなたがGroovy生態系であなたのコードにとどまるならば、心配する何もありません.しかし、時々Groovyを使用して、純粋なJavaプロジェクトでも使用できるライブラリコードを記述します.あなたは新しい';@ Pojo ';注釈と一緒にこれらの2つの世界をもたらすことができます.で指定されたクラス@POJO 注釈は、ランタイムでgroovyを追加せずに使用できます.と同じようにPojoPoint この例で示すクラスです.Javaプログラムとしてコンパイルして実行しましょう.
import groovy.transform.CompileStatic
import groovy.transform.Immutable
import groovy.transform.stc.POJO

@POJO
@Immutable
@CompileStatic
class PojoPoint {
    int x, y

    static void main(String[] args) {
        PojoPoint point = new PojoPoint(1,1)
        System.out.println(point.toString())
    }
}

特徴懸垂7:グルーヴィー契約


あなたが防御コードを書くのに疲れているならば、Groovy契約は祝福であるかもしれません.The @Invariant クラス注釈は、コンストラクタ呼び出し後、メソッド呼び出しの前、後にオブジェクトの生存期間中にチェックされるアサーションを定義します.The @Requires 注釈はメソッド前提条件を表します-メソッド呼び出しの前に実行される表明.と@Ensures 注釈はメソッドの条件として動作します-メソッド呼び出しの後に実行されるアサーション.これらの注釈を簡単に、メソッドの本体の明示的なアサーションで置き換えることができると言う人もいます.そして、それは本当です.しかし、契約とビジネスロジックをうまく分離したい場合は、Groovy契約を開始する良い場所のように聞こえる.
import groovy.contracts.Ensures
import groovy.contracts.Invariant
import groovy.contracts.Requires

@Invariant({ speed >= 0 })
class Rocket {
    int speed = 0
    boolean started = false

    @Requires({ !started })
    Rocket startEngine() { tap {started = true }}

    @Requires({ started })
    Rocket stopEngine() { tap { started = false }}

    @Requires({ started })
    @Ensures({ old.speed < speed })
    Rocket accelerate(int value) { tap { speed += value }}
}

主な特徴


統合クエリ言語.あなたがSQLのような言語のファンなら、この機能を気に入るはずです.Ginqを使用すると、SQLのような構文を使用してコレクションを照会できます.この例と同じように.を含むJSONドキュメントを持っていますpeople フィールド.私たちはGinqを使用して、18 +であるすべての人々を見つけるために、降順で、最初の3つの結果を取って、返されたデータを上位にして、最初の2つの手紙だけに制限されるように変更します.私の知る限り、GroovyチームはGinqをSQLデータベースをサポートするように拡張し、コンパイル時に生成されたSQLクエリを生成できるようにする予定です.
import groovy.json.JsonSlurper

def json = new JsonSlurper().parseText '''
    {
        "people": [
            {"name": "Alan", "age": 11},
            {"name": "Mary", "age": 26},
            {"name": "Eric", "age": 34},
            {"name": "Elisabeth", "age": 14},
            {"name": "Marc", "age": 2},
            {"name": "Robert", "age": 52},
            {"name": "Veronica", "age": 32},
            {"name": "Alex", "age": 17}
        ]
    }
    '''

assert GQ {
    from f in json.people
    where f.age >= 18
    orderby f.age in desc
    limit 3
    select f.name.toUpperCase().take(2)

}.toList() == ['RO', 'ER', 'VE']

機能注意9 : TOMLサポート


Groovy 3はYAML形式のサポートを追加しました.コードベースでこのような形式で動作している場合に便利です.TomilBuilderクラスによって生成された出力は、テーブルヘッダーを生成しませんが、代わりにドット区切りのフィールド名を生成しないことに注意してください.
import groovy.toml.TomlBuilder
import groovy.toml.TomlSlurper

String input = '''
# This is a TOML document (taken from https://toml.io)

title = "TOML Example"

[owner]
name = "Tom Preston-Werner"
dob = 1979-05-27T07:32:00-08:00

[database]
enabled = true
ports = [ 8000, 8001, 8002 ]
data = [ ["delta", "phi"], [3.14] ]
temp_targets = { cpu = 79.5, case = 72.0 }

[servers]

[servers.alpha]
ip = "10.0.0.1"
role = "frontend"

[servers.beta]
ip = "10.0.0.2"
role = "backend"
'''

def toml = new TomlSlurper().parseText(input)

assert toml.title == 'TOML Example'
assert toml.owner.name == 'Tom Preston-Werner'
assert toml.database.ports == [8000, 8001, 8002]
assert toml.servers.alpha.ip == '10.0.0.1'
assert toml.servers.beta.ip == '10.0.0.2'


TomlBuilder builder = new TomlBuilder()
builder {
    title 'This is TOML document'
    servers {
        alpha {
            ip '10.0.0.1'
        }
        beta {
            ip '10.0.0.2'
        }
    }
}
assert builder.toString() ==
'''title = 'This is TOML document'
servers.alpha.ip = '10.0.0.1'
servers.beta.ip = '10.0.0.2'
'''

特徴は、10を含みます:JDK 8互換性


Groovy 4を実行するのに必要な最小のJavaバージョンはJDK 8です.あなたは尋ねるかもしれません-しかし、Groovyはどのように扱われますか?それをあなたに見せましょう.ここにJava 17とGroovy 4.0.1があります.私はこのスクリプトをクラスファイルにコンパイルするつもりです、そして、我々がIntellijでそれを開くとき、我々は予想されるようにJavaネイティブ記録を等価にするのを見ることができます.さあ、Java 8に切り替えて、同じことをしましょう.IntelliJでクラスファイルを開くと、生成されたクラスはレコードの振る舞いを「エミュレート」するが、ネイティブのレコード構文を使用しないことがわかります.そして、それはGroovyのコードの移植性の美しさ-同じコードとブランドの新しい言語の機能は、かなり古いJavaのバージョンでも動作します.

ソースコード


ウロロック / Groovy - 4例



グルービー4例



最新のGroovyをインストールする


SDKのインストール
SDKMANを取得するhttps://sdkman.io/

Groovyコマンドで単一のスクリプトを実行する


CDサンプル
グルーヴィー01 .グルービー

Gradleを使用して単一のスクリプトを実行する


/gradleW - q runscript - pmainclass = 01 . 1 basiChangeSwitchHeight式

Gradleを使用して全てのスクリプトを実行する


chmod + x/runallsh
/runallsh
View on GitHub