開発者ドキュメント

Groovy言語の紹介


1概要

  • Groovyは、JVM ** 用の動的なスクリプト言語です。バイトコードにコンパイルし、Javaコードおよびライブラリとシームレスにブレンドします。

この記事では、基本的な構文、制御構造、コレクションなど、http://www.groovy-lang.org/[Groovy]の重要な機能をいくつか紹介します。

それから、我々はそれを魅力的な言語にする主な特徴のいくつかを見ていくでしょう。


2環境

MavenプロジェクトでGroovyを使用したい場合は、__pom.xmlに以下を追加する必要があります。

<build>
    <plugins>
       //...
        <plugin>
            <groupId>org.codehaus.gmavenplus</groupId>
            <artifactId>gmavenplus-plugin</artifactId>
            <version>1.5</version>
       </plugin>
   </plugins>
</build>
<dependencies>
   //...
    <dependency>
        <groupId>org.codehaus.groovy</groupId>
        <artifactId>groovy-all</artifactId>
        <version>2.4.10</version>
    </dependency>
</dependencies>

最新のMavenプラグインはhttps://mvnrepository.com/artifact/org.codehaus.gmavenplus/gmavenplus-plugin[ここ]および最新バージョンの

groovy-all


https://mvnrepository.com/artifact/orgにあります。

.codehaus.groovy/groovy-all[ここ]。


3基本的な機能

Groovyには多くの便利な機能があります。それでは、言語の基本的な構成要素と、それがJavaとどう違うのかを見てみましょう。

それでは、言語の基本的な構成要素と、それがJavaとどう違うのかを見てみましょう。


3.1. 動的タイピング

Groovyの最も重要な機能の1つは、動的型付けのサポートです。

型定義はオプションであり、実際の型は実行時に決定されます。これら2つのクラスを見てみましょう。

class Duck {
    String getName() {
        'Duck'
    }
}
class Cat {
    String getName() {
        'Cat'
    }
}

これら2つのクラスは同じ

getName

メソッドを定義していますが、コントラクトでは明示的に定義されていません。

さて、

getName

メソッドを持つアヒルと猫を含むオブジェクトのリストがあると想像してください。 Groovyでは、次のことが可能です。

Duck duck = new Duck()
Cat cat = new Cat()

def list =[duck, cat]list.each { obj ->
    println obj.getName()
}

コードがコンパイルされ、上記のコードの出力は次のようになります。

Duck
Cat

* 3.2。暗黙的なTruthy変換**

JavaScriptのように、Groovyは必要に応じてすべてのオブジェクトをブール値に評価します。

if

ステートメント内で使用する場合、または値を否定する場合

if("hello") {...}
if(15) {...}
if(someObject) {...}

この変換について覚えておくべき簡単な規則がいくつかあります。

  • 空でない

    Collections、

    配列、マップは

    true

    に評価されます

  • 少なくとも1つの一致を持つ

    Matcher



    true

    に評価されます


  • Iterators



    Enumerations

    は他の要素と一緒に強制されます




** 空でない

Strings



GStrings



CharSequences

は、




** ゼロ以外の数は

true

に評価されます

  • null以外のオブジェクト参照は

    true

    に強制変換されます

暗黙の真の変換をカスタマイズしたい場合は、

asBoolean()

メソッドを定義できます。


3.3. 輸入品

一部のパッケージはデフォルトでインポートされます。明示的にインポートする必要はありません。

import java.lang.**
import java.util.**
import java.io.**
import java.net.**

import groovy.lang.**
import groovy.util.**

import java.math.BigInteger
import java.math.BigDecimal


4 AST変換

AST(

Abstract Syntax Tree

)変換を使用すると、Groovyのコンパイルプロセスを利用してニーズに合わせてカスタマイズすることができます。これはコンパイル時に行われるため、アプリケーションを実行してもパフォーマンスが低下することはありません。 AST変換を作成できますが、組み込みの変換も使用できます。

私たちは自分たちの変容を生み出すことができます、あるいは組み込みのものから利益を得ることができます。

知っておく価値のあるいくつかの注釈を見てみましょう。


4.1. アノテーション

Typeチェック済み


この注釈は、注釈付きのコード部分に対して厳密な型チェックをコンパイラに実行させるために使用されます。型チェックメカニズムは拡張可能なので、必要に応じてJavaで利用可能なものよりもさらに厳密な型チェックを提供することさえ可能です。

以下の例を見てみましょう。

class Universe {
    @TypeChecked
    int answer() { "forty two" }
}

このコードをコンパイルしようとすると、次のエラーが発生します。

----[Static type checking]- Cannot return value of type java.lang.String on method returning type int
----


@ TypeChecked

アノテーションはクラスとメソッドに適用できます。


4.2. アノテーション

CompileStatic


このアノテーションにより、コンパイラはJavaコードと同様にコンパイル時チェックを実行できます。その後、コンパイラは静的コンパイルを実行し、Groovyメタオブジェクトプロトコルを迂回します。

クラスに注釈が付けられると、その注釈付きクラスのすべてのメソッド、プロパティ、ファイル、内部クラスなどが型チェックされます。メソッドに注釈が付けられている場合、静的コンパイルはそのメソッドで囲まれている項目(クロージャと無名の内部クラス)にのみ適用されます。


5プロパティ

Groovyでは、JavaのPOJOと同じように機能するPOGO(Plain Old Groovy Objects)を作成できますが、コンパイル時に

getterおよびsetterがパブリックプロパティ

に対して自動的に生成されるため、よりコンパクトになります。それらがまだ定義されていない場合にのみ生成されることを覚えておくことが重要です。

これにより、値を設定または取得するときの動作をオーバーライドする機能を保持しながら、属性をオープンフィールドとして定義する柔軟性が得られます。

このオブジェクトを考慮してください。

class Person {
    String name
    String lastName
}

クラス、フィールド、およびメソッドのデフォルトのスコープは

public –

なので、これはパブリッククラスであり、2つのフィールドはpublicです。

コンパイラはこれらをプライベートフィールドに変換し、

getName()



setName()



getLastName()

、および

setLasfName()

メソッドを追加します。特定のフィールドに対して

setter



getter

を定義した場合、コンパイラはpublicメソッドを作成しません。


5.1. ショートカット表記

Groovyは、プロパティを取得および設定するためのショートカット表記を提供しています。

ゲッターやセッターを呼び出すJavaの方法の代わりに、フィールドのようなアクセス表記法を使うことができます。

resourceGroup.getResourcePrototype().getName() == SERVER__TYPE__NAME
resourceGroup.resourcePrototype.name == SERVER__TYPE__NAME

resourcePrototype.setName("something")
resourcePrototype.name = "something"


6. 演算子

それでは、プレーンJavaで知られているものに加えて追加された新しい演算子を見てみましょう。


6.1. NULLセーフな間接参照

最も一般的なものは、nullセーフの間接参照演算子

“?”

です。チェーンのどこかの時点で

null

値が発生する可能性がある連鎖呼び出しでは特に便利です。

たとえば、安全に電話をかけることができます。

String name = person?.organization?.parent?.name

上記の例で、

person



person.organization

、または

organization.parent



null

の場合、

null

が返されます。


6.2. エルビスオペレータ

Elvis演算子

“?:

”を使用すると、3項式を圧縮できます。これら二つは同等です:

String name = person.name ?: defaultName

そして

String name = person.name ? person.name : defaultName

両方とも

Groovy true

(この場合、

null

ではなく

non-zero

の長さ)であれば、両方ともname変数に

person.name

の値を割り当てます。


6.3. 宇宙船オペレーター

スペースシップ演算子

“ <⇒”

は、2つのオブジェクトを比較し、両方の引数の値に応じて-1、0、または1を返す、Javaの

compareTo()

のように動作する関係演算子です。

左の引数が右より大きい場合、演算子は1を返します。

左の引数が右より小さい場合、演算子は-1を返します。引数が等しい場合は、0が返されます。

比較演算子を使用する最大の利点は、

x <⇒ y



NullPointerException

をスローしないように

nulls

をスムーズに処理できることです。

println 5 <=> null

上記の例は結果として1を印刷します。


7. 文字列

文字列リテラルを表現する方法は複数あります。 Javaで使用される方法(二重引用符で囲まれた文字列)はサポートされていますが、必要に応じて一重引用符を使用することもできます。

他の言語ではheredocsと呼ばれることもある複数行の文字列もサポートされ、三重引用符(一重または二重)を使用します。

他の言語ではheredocsと呼ばれることもある複数行の文字列もサポートされ、三重引用符(一重または二重)を使用します。

二重引用符で定義された文字列は、

$ \ {}

構文を使った補間をサポートします。

def name = "Bill Gates"
def greeting = "Hello, ${name}"

実際、任意の式を

$ \ {}

の内側に配置できます。

def name = "Bill Gates"
def greeting = "Hello, ${name.toUpperCase()}"

二重引用符を含む文字列に

$ \ {}

という式が含まれている場合、それはGStringと呼ばれます。それ以外の場合は、プレーンな

String

オブジェクトです。

以下のコードはテストに失敗することなく実行されます。

def a = "hello"
assert a.class.name == 'java.lang.String'

def b = 'hello'
assert b.class.name == 'java.lang.String'

def c = "${b}"
assert c.class.name == 'org.codehaus.groovy.runtime.GStringImpl'


8コレクションと地図

基本的なデータ構造がどのように処理されるのかを見てみましょう。


8.1.

リスト


これが、Javaの

ArrayList

の新しいインスタンスにいくつかの要素を追加するためのコードです。

List<String> list = new ArrayList<>();
list.add("Hello");
list.add("World");

これがGroovyの同じ操作です。

List list =['Hello', 'World']----

リストはデフォルトでは__java.util.ArrayList__型であり、対応するコンストラクタを呼び出すことによって明示的に宣言することもできます。

__Set__には別の構文はありませんが、そのためには__coercion__型を使用できます。どちらでも使えます:

[source,groovy,gutter:,true]

Set greeting =[‘Hello’, ‘World’]—-

または

def greeting =['Hello', 'World']as Set


8.2.

地図


コロンで区切られたキーと値を指定できるようにする必要があるので、

Map

の構文は似ていますが、もう少し冗長ですが。

def key = 'Key3'
def aMap =[    'Key1': 'Value 1',
    Key2: 'Value 2',
    (key): 'Another value']----

この初期化の後に、エントリ__Key1  - > Value1、Key2  - > Value 2、Key3  - > Another Value__を持つ新しい__LinkedHashMap__が得られます。

マップ内のエントリには、さまざまな方法でアクセスできます。

[source,groovy,gutter:,true]

println aMap[‘Key1’]println aMap[key]println aMap.Key1

===  **  9制御構造**

====  **  9.1. 条件式:__if-else__ **

Groovyは、期待通りに条件付き__if/else__構文をサポートします。

[source,groovy,gutter:,true]

if (…​) {
//…​
} else if (…​) {
//…​
} else {
//…​
}

====  **  9.2. 条件式:__スイッチケース__ **

__switch__ステートメントはJavaコードと下位互換性があるため、複数の一致に対して同じコードを共有するケースを回避できます。

最も重要な違いは、__スイッチ__が複数の異なる値型に対してマッチングを実行できることです。

[source,groovy,gutter:,true]

def x = 1.23
def result = “”

switch ( x ) {
case “foo”:
result = “found foo”
break

case "bar":
    result += "bar"
    break
case[4, 5, 6, 'inList']:
    result = "list"
    break
case 12..30:
    result = "range"
    break
case Number:
    result = "number"
    break
case ~/fo** /:
    result = "foo regex"
    break
case { it < 0 }://or { x < 0 }
    result = "negative"
    break
    default:
        result = "default"
}

println(result)

上記の例は__番号を印刷します。

====  **  9.3. ループ:__while__ **

Groovyは、Javaのように通常の__while__ループをサポートします。

[source,groovy,gutter:,true]

def x = 0
def y = 5

while ( y– > 0 ) {
x++
}

====  **  9.4. ループ:__for__ **

Groovyはこの単純さを受け入れ、この構造に従う__for__ループを強く推奨します。

[source,groovy,gutter:,true]

for (variable in iterable) { body }

__for__ループは__iterable__に対して繰り返します。頻繁に使用される反復可能オブジェクトは、範囲、コレクション、マップ、配列、反復子、および列挙型です。実際、どのオブジェクトもイテラブルになることができます。

本体の周りの中括弧は、それが1つのステートメントだけで構成されている場合はオプションです。以下は__range__、__list__、__array__、__map__、および__strings__を反復処理する例です。

[source,groovy,gutter:,true]

def x = 0
for ( i in 0..9 ) {
x += i
}

x = 0
for ( i in[0, 1, 2, 3, 4]) {
x += i
}

def array = (0..4).toArray()
x = 0
for ( i in array ) {
x += i
}

def map =[‘abc’:1, ‘def’:2, ‘xyz’:3]x = 0
for ( e in map ) {
x += e.value
}

x = 0
for ( v in map.values() ) {
x += v
}

def text = “abc”
def list =[]for (c in text) {
list.add(c)
}

オブジェクトの反復はGroovyの____for -____ループを洗練された制御構造にします。 __Collectionのeach__メソッドを使用するなど、クロージャを使用してオブジェクトを反復処理するメソッドを使用するのは有効な方法です。

主な違いは、__for__ループの本体がクロージャではないということです。つまり、この本体はブロックです。

[source,groovy,gutter:,true]

for (x in 0..9) { println x }

これに対して、この本体はクロージャです。

[source,groovy,gutter:,true]

(0..9).each { println it }

外観は似ていますが、構造が大きく異なります。

クロージャはそれ自身の目的であり、異なる機能を持っています。それは別の場所で構築して__each__メソッドに渡すことができます。

ただし、____for -____ループの本体は、その出現時点で__bytecode__として直接生成されます。特別なスコープ規則は適用されません。

===  **  10例外処理**

大きな違いは、チェック済み例外処理が強制されていないことです。

一般的な例外を処理するために、例外の原因となる可能性のあるコードを__try/catch__ブロックに配置できます。

[source,groovy,gutter:,true]

try {
someActionThatWillThrowAnException()
} catch (e)
//log the error message, and/or handle in some way
}

我々がキャッチする例外のタイプを宣言しないことによって、どんな例外もここでキャッチされるでしょう。

===  **  11クロージャ**

簡単に言うと、クロージャーは変数に渡すことができ、それが定義されたコンテキストでデータにアクセスできる実行可能コードの無名ブロックです。

これらは匿名の内部クラスにも似ていますが、インターフェイスを実装することも基本クラスを拡張することもしません。それらはJavaのラムダに似ています。

興味深いことに、Groovyはラムダ、特にストリーミングAPIをサポートするために導入されたJDKの追加を最大限に活用することができます。

ラムダ式が期待されるところでは、常にクロージャを使うことができます。

以下の例を考えてみましょう。

[source,groovy,gutter:,true]

def helloWorld = {
println “Hello World”
}

変数__helloWorld__はクロージャへの参照を保持しており、__call__メソッドを呼び出すことで実行できます。

[source,groovy,gutter:,true]

helloWorld.call()

Groovyでは、より自然なメソッド呼び出し構文を使用できます。それは__call__メソッドを呼び出します。

[source,groovy,gutter:,true]

helloWorld()

====  **  11.1. パラメーター**

メソッドと同様に、クロージャはパラメータを持つことができます。 3つの変種があります。

後者の例では、declpersistence__startaredは何もないので、デフォルト名__it__を持つパラメータは1つだけです。送信された内容を表示するように修正されたクロージャーは次のようになります。

[source,groovy,gutter:,true]

def printTheParam = { println it }

これを次のように呼ぶことができます。

[source,groovy,gutter:,true]

printTheParam(‘hello’)
printTheParam ‘hello’

クロージャ内のパラメータを期待し、呼び出すときにそれらを渡すこともできます。

[source,groovy,gutter:,true]

def power = { int x, int y →
return Math.pow(x, y)
}
println power(2, 3)

パラメータの型定義は変数と同じです。型を定義すると、この型のみを使用できますが、使用可能で、必要なものをすべて渡すこともできます。

[source,groovy,gutter:,true]

def say = { what →
println what
}
say “Hello World”

====  **  11.2. オプションの返品**

クロージャの最後のステートメントは、returnステートメントを書く必要なしに暗黙のうちに返されるかもしれません。これは、定型コードを最小限に抑えるために使用できます。したがって、数の二乗を計算するクロージャは次のように短くすることができます。

[source,groovy,gutter:,true]

def square = { it ** it }
println square(4)

このクロージャは、暗黙のパラメータ__it__とオプションのreturn文を使用します。

===  **  12. **  ** 結論**

この記事では、Groovy言語とその主な機能について簡単に紹介しました。基本的な構文、条件付きステートメント、演算子などの簡単な概念を紹介することから始めました。また、演算子やクロージャなど、より高度な機能もいくつか紹介しました。

その言語とそのセマンティクスについてもっと知りたい場合は、http://www.groovy-lang.org/semantics.html[公式サイト]に直接アクセスしてください。
モバイルバージョンを終了