技術メモ

技術メモ

ラフなメモ

Groovyに入門した

Gradleに入門するにあたって予めGroovyの記述方法について理解しているほうがGradleのbuild.gradleの記述方法がわかりやすくなると考えています。この記事では、groovyに関する一通りの文法を抑えることをゴールとします。

前提

以下の環境で確認しています。

環境 バージョン
Groovy 3.0.0-alpha-4

Eclipse上にGroovyプロジェクトを作成しています。その中で sample.groovy ファイルを実行しています。

言語仕様

Groovyの言語仕様はJavaのそれをベースとしており、基本的にJavaプログラマにとって慣れ親しみやすいものである。Groovyはスクリプト言語として大幅に簡易化された記述を許している。以下に簡略な記述を可能とするGroovy言語の特徴を示す。

https://ja.wikipedia.org/wiki/Groovy」より引用

セミコロンは省略可能

いろいろ省略できます。スクリプト言語という感じです。

print 1 // セミコロンが不要
// 1

returnも省略可能

String hello() {
    // return が不要
    "Hello Gradle!"
}

print hello()
// Hello Gradle!

チェック例外のthrow宣言も省略可能

// throw 句は不要
String doException() {
    throw new Exception("チェック例外:-(")
}

try {
    doException()
    print "hoge"
} catch (Exception e) {
    print e.getMessage()
}
// チェック例外:-(

型宣言も省略可能

def キーワードが使えます。def キーワードで宣言した場合は Object 型になります。

def a = 1
def b = 0.1
def c = "three"

println a
println b
println c
// 1
// 0.1
// three

def キーワードすら省略することができます。いい感じに型推論してくれます。

d = "foo"
e = 0.1
println d.getClass()
println e.getClass()
// class java.lang.String
// class java.math.BigDecimal

プリミティブ型はラッパー型

こんなことができます。

println 1.getClass()
// class java.lang.Integer

各種リテラル

文字列リテラルの基本はダブルクォーテーションです。変数の展開は ${} でできます。シェルみたいですね。

println "Hello, World!"

String name = "World!!"
println "Hello, ${name}"
// Hello, World!
// Hello, World!!

正規表現/ / のように記述できます。Javaではバッククォートをエスケープする必要がありましたが、groovyでは必要がありません。

println "Hello, World".matches(/Hello,\s.*/)
// true

アクセス修飾子

基本的にすべて public になります。なので以下のコードの private は意味を成していません。

class Hoge {
    private f;
    private m(){}
}

x = new Hoge()
x.f
x.m()
// (エラーは起きない)

メソッド呼び出し

引数の丸かっこを省略することができます。

println("hoge")
println "hoge"
// hoge
// hoge

Gradleでの以下のような記述はメソッド呼び出しと同じです。

compile 'org.apache.commons:commons-lang3:3.9'
compile('org.apache.commons:commons-lang3:3.9')

メソッドの引数の型も省略できます。

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

println add(1, 2)
// 3

デフォルト引数を定義できます。

def say(name = "Default") {
    "Hello, ${name}!"
}

println say()
println say("World")
// Hello, Default!
// Hello, World!

名前付きパラメータを渡すこともできます。

def foo(Map args) {
    println "${args.name}: ${args.age}"
}
foo(name: 'Marie', age: 1)
// Marie: 1

Gradleでの以下のような記述はメソッド呼び出しと同じです。
メソッドの丸かっこが省略されています。

apply plugin: 'java'
apply(plugin: 'java')

コンストラクタ呼び出し

new するときにパラメータを指定して値を代入することができます。

class Sample {
    String a
    String b
    Integer c
}

def sample = new Sample(a: "A", b: "B", c: 3)
println sample.dump()
// <Sample@62fe6067 a=A b=B c=3>

デフォルトのimport定義

以下はデフォルトで import 済です。

0 や null は false です

0 は false 扱いなので以下のコードは -1 は出力されません。C++っぽい感じがします。

int num = 5
while (num--) {
    println num
}
// 4
// 3
// 2
// 1
// 0

for文あれこれ

Javaの拡張for文の : は in に変えることができます。

for(i = 0; i < 10; i++){
    print i
}

for(String s : ["a", "b", "c"]){
    print s
}

for(s in ["a", "b", "c"]){
    print s
}
// 0123456789abcabc

if文あれこれ

普通の if 文が書けます。ちなみにIntegerクラスの値を == で比較していますが、Groovyの場合はequals呼び出しになります。Stringクラスも同様に == で比較することができます。

def value = 1
if (value == 1) {
    println "value is ${value}."
}
// value is 1.

assert が便利です。評価式がtrueの場合は何も起きませんがfalseの場合は以下のように Assertion failed が発生します。

assert 1 == 2
// Caught: Assertion failed: 

// assert 1 == 2
//          |
//          false

// Assertion failed: 

// assert 1 == 2
//          |
//          false

//     at sample.run(sample.groovy:1)

どれも groovy では空です。

assert "empty" == ([] ? "full" : "empty")
assert "empty" == ([:] ? "full" : "empty")
assert "empty" == (0 ? "full" : "empty")
assert "empty" == ("" ? "full" : "empty")

Listあれこれ

以下のように List を初期化することができます。

List list = [1, 2, 3, 4]
println "size of list is ${list.size()}."
list.each {
    println it
}
// size of list is 4.
// 1
// 2
// 3
// 4

Mapあれこれ

Mapは以下のように定義できます。[キー:値]という形式になっています。

Map map = [a: "foo", b: "bar"]

// 値の取得
assert map.a == "foo"
assert map.get("a") == "foo"
assert map["a"] == "foo"

// 値の追加
map["hoge"] = "value"
assert map.size() == 3
assert map["hoge"] == "value"

クロージャ

以下のようにクロージャを定義できます。

// クロージャの定義
c = {
    "Hello, Closure!"
}

// 実行
assert c.call() == "Hello, Closure!"

// callは省略可能
assert c() == "Hello, Closure!"
クロージャでの引数の扱い

Javaラムダ式な感じですね。

引数なし
def c0 = { ->
    "Hello, Closure"
}

assert c0() == "Hello, Closure"
引数1つ
def c1 = { String name ->
    "Hello, ${name}"
}

assert c1("Closure") == "Hello, Closure"

静的Groovy

コンパイル時(groovyc)に型のチェックを行うことができます。

@CompileStatic をつけるだけです。

参考