Think Twice
IT技術メモ | Groovyのメモ
Created: 2010-06-05 / Updated: 2021-04-08

Groovy基礎文法最速マスター


当メモは2010-06-05に投稿されたものを加筆修正し、再掲したものです。
当初の掲載からだいぶ時間が経過していますので、古い内容のものもあると思いますのでご注意下さい。
順次アップデートしていく予定です。

目次


はじめに

GroovyはJavaのシンタクスシュガーな上位互換として設計されており、
妥当なJavaプログラムであれば、ほぼそのままでGroovyプログラムとして動かすことができます(参照)。
誤解を恐れずに言うならば、現存するプログラミング言語中でもっともJavaと親和性の高いBetter Javaな言語、
それがGroovyであるということです(唯一の違いは拡張子が.javaではなく.groovyであることくらいです)。
Groovyを利用すれば世界中に存在する有益なJava資産をすべて利用することができます
また、スクリプトとしてではなく.classファイルにコンパイルすることも可能です。
コンパイルすることで通常のJavaプログラムと同等の動作スピードを得ることができます。

なお、上記のような特徴から、Javaを全く知らない人よりも、Javaをある程度知っている人がGroovyを学習することで、
爆発的なパワーを手に入れることができるようになると思います。

1. 基礎

Groovyの実行

コマンド 説明
groovy Groovyスクリプトを実行するインタプリタを起動します。
コマンドライン引数として1行だけのGroovyスクリプトを指定することもできます。
groovysh Groovyコードを対話的に実行するためのコマンドラインシェルを起動します。
文やスクリプトを1行ごとに入力しコードをその場で実行することができます。
groovyConsole Groovyコードを対話的に実行するためのグラフィカルインタフェースを起動します。
GroovyConsoleはGroovyスクリプトファイルをロードして実行することもできます。

表示 (print, println, printf)

表示
Copy
print 'Hello, Groovy!!'        // 改行なし
println 'Hello, Groovy!!'      // 改行あり
printf 'Hello, %s', 'Groovy!!' // 整形して表示

コメント

コメント
Copy
// 一行コメント
/* 複数行コメント */
/** Groovydoc(Javadoc)コメント */

括弧やセミコロンの省略

Groovyではコードの解釈に支障がない場合に限り、括弧やセミコロンの省略が可能です。

括弧やセミコロンの省略
Copy
println("hi");
println("hi")
println "hi"

アサーション

Groovyではどこでもassert文を利用できます。
コード内にassertテストを埋め込んでコードの正当性を保つのがGroovyのスタイルです。

書式
Copy
assert 式, コメント
Copy
def a = 10
def b = 20
assert 30 == a + b, '足したら30のはず'

以降、サンプルコードでもassert文を利用します。

等値性と同一性

#equals()====#is()
分かりにくいので、Javaと比較すると以下のようになります。

Groovy Java
等値性 a == b a.equals(b)
同一性 a.is(b) a == b

また、nullに対してもチェック可能です。

等値性と同一性
Copy
assert null == null
assert !(null == 1)

2. データ型

すべてがObject(プリミティブはない)

11.0fなどのJavaでのプリミティブは java.lang.Integerや、java.lang.Floatなどのラッパーでラッピングされているため、
通常のリテラルのように利用することが可能となります。

数値型リテラル

数値型リテラルとして利用できるものは、以下表のようになります。

エイリアス リテラル例
java.lang.Integer int 15, 0x1234ffff
java.lang.Long long 100L, 200l*9
java.lang.Float float 1.23f, 4.56F
java.lang.Double double 15, 0x1234ffff
java.lang.BigInteger - 123g, 456G
java.lang.BigDecimal - 1.23, 4.56, 1.4E4, 2.8e4, 1.23g, 1.23G

def (型の指定)

defキーワードはどんな型でもよいということを示すために使われます。
明示的に型を指定してもよいです。

型の指定
Copy
def a = 1      // => 実際の型はjava.lang.Integer (暗黙の型付け)
def b = 1.0f   // => 実際の型はjava.lang.Float   (暗黙の型付け)
int c = 1      // => 実際の型はjava.lang.Integer (Javaの基本型を使った明示的な型付け)
float d = 1    // => 実際の型はjava.lang.Float   (Javaの基本型を使った明示的な型付け)
Integer e = 1  // => 実際の型はjava.lang.Integer (参照型の型名を使った明示的な型付け)
String f = '1' // => 実際の型はjava.lang.String  (参照型の型名を使った明示的な型付け)
intfloatなどはjava.lang.Integerjava.lang.Floatのエイリアスです。

演算子のオーバーライド

たとえば、1 + 11.plus(1) の便利な書き方に過ぎません。
これはIntegerクラスがplusメソッドの実装を持つことによって実現されています。
これは他の演算子についても可能で自作クラスにも適用できますJavaと違って特定のインタフェース実装は必要ありません
主な例を示します。

演算子 名前 メソッド
a + b 加算 a.plus(b)
a - b 減算 a.minus(b)
a * b 乗算 a.multiply(b)
a / b 除算 a.div(b)
a % b 剰余 a.mod(b)
a ** b べき乗 a.power(b)
a << b 左シフト a.leftShift(b)
a >> b 右シフト a.rightShift(b)
a >>> b 論理右シフト a.rightShiftUnsigned(b)
a & b ビット積 a.and(b)
a | b ビット和 a.or(b)
a ^ b 排他的ビット和 a.xor(b)
a == b
a != b
等値判定 a.equals(b)
(aがComparableを実装している場合は、a.compareTo(b))
a < b
a > b
a <= b
a >= b
a <=> b
大小比較 a.compareTo(b)
a as b 強制型変換 a.asType(b)
a in b 包含判定 a.isCase(b)
a++
++a
インクリメント a.next()
a--
--a
デクリメント a.previous()
+a 単項プラス a.positive()
-a 単項マイナス a.negative()
~a ビット否定 a.bigwiseNegate()
a[b] 添字 a.getAt(b)
a[b] = c 添字代入 a.putAt(b, c)

文字列

文字列リテラルは3種類あります。

シングルクォート文字列

1つ目はシングルクォートを用いるものです。こちらは通常の文字列として扱われます。java.lang.Stringと等価です。

通常の文字列(java.lang.Stringと等価)
Copy
def str = 'シングルクォート'

ダブルクォート文字列

2つ目はダブルクォートを用いるものです。こちらは以下のように変数($の後に変数名)や式を埋め込むことができます。groovy.lang.GStringと等価です。

変数埋め込み可能文字列
Copy
def a = 'world'
def str1 = "hello $a"
def str2 = "hello ${a}"
assert str1 == str2
assert str1 == 'hello world'

スラッシュ文字列

3つ目はスラッシュ/を用いるものです。こちらはバックスラッシュ\をエスケープせずに利用できるため、正規表現を埋め込む際に利用されます。それ以外はダブルクォートのものと同様です。

バックスラッシュがエスケープされない文字列(正規表現用)
Copy
def pathStr = /C:\temp\xxxx/  // バックスラッシュがそのまま使える
def regexpStr = /^\d{4}-\d{3}/  // 正規表現を宣言する時に便利
def color = 'blue'
def interpolatedSlashy = /a ${color} car/  // 変数埋め込みも可能

ドルスラッシュ文字列

4つ目はドルスラッシュ$//$を用いるものです。基本的にはスラッシュ文字列と同じなのですが、文字列中のエスケープ文字が\ではなく、$になったものです。

バックスラッシュがエスケープされない文字列(エスケープ文字は$)
Copy
def pathStr = $/C:\temp\xxxx/$  // バックスラッシュがそのまま使える
def regexpStr = $/^\d{4}-\d{3}/$  // 正規表現を宣言する時に便利
def color = 'blue'
def interpolatedSlashy = $/a ${color} car/$  // 変数埋め込みも可能
def interpolatedSlashy2 = $/a $${color} car/$  // $でエスケープも可能

複数行文字列

上記4つの文字列の複数行文字列1もリテラルレベルでサポートされています。
シングルクォートとダブルクォートはそれぞれ3つにすることで複数行文字列として利用可能です。
スラッシュ文字列とドルスラッシュ文字列は最初から複数行文字列として利用可能です。

複数行文字列(ヒアドキュメント)
Copy
// シングルクォート文字列の複数バージョン
def multiStr1 = '''
これは
複数行の
文字列です。
'''

// シングルクォート文字列の複数バージョン
def multiStr2 = """
本日は
${new Date()}
なり。
"""

def color = 'blue'

// スラッシュ文字列
def multiStr3 = /
C:\temp\xxxx
^\d{4}-\d{3}
a ${color} car
/

// ドルスラッシュ文字列
def multiStr4 = $/
a ${color} car
a $${color} car
/$

文字列のまとめ

まとめると以下表のようになります。

文字列の名称 シンタックス 変数埋め込み 複数行 エスケープ文字
シングルクォート文字列 '…' 不可 不可 \
トリプルシングルクォート文字列 '''…''' 不可 \
ダブルクォート文字列 "…" 不可 \
トリプルダブルクォート文字列 """…""" \
スラッシュ文字列 /…/ \
ドルスラッシュ文字列 $/…/$ $

3. 文法

文は1行にひとつ書きます。セミコロン;を付けることで、1行に複数の文を記述することができます。

文(行で分割)
Copy
文1
文2
文(セミコロンで分割)
Copy
文1; 文2

制御構造

if-else

単一行のif
Copy
if (false) assert false
nullは偽
Copy
if (null) {
  assert false
} else {
  assert true
}

while

while
Copy
def i = 0
while (i < 10) {
  i++
}
assert i == 10

do

Groovyにdoはありません。2

for

昔ながらのfor
Copy
for (i = 0; i < 10; i++) {
  println i
}
範囲に対するfor
Copy
def clinks = 0
for (remainingGuests in 0..9) {
  clinks += remainingGuests 
}
リストに対するfor
Copy
def list = [0, 1, 2, 3, 4, 5]
for (j in list) {
  assert j == list[j]
}

switch

switch
Copy
switch(3) {
  case 1 : assert false; break
  case 3 : assert true;  break
  default: assert false
}

try-catch-finally

try-catch-finally
Copy
try {
  // 処理
} catch(e) {
  // 例外e発生時処理
} finally {
  // 最終処理
}

return/break/continue

return, break, continueの一般的なロジックはJavaと同じです。
ただし、Groovyではreturnが省略可能です。省略した場合、最後に評価された値が返却されます。

returnは省略可能、返却値は最後に評価されたもの
Copy
def method() {
  def a = 10
  def b = 20
  a + b
}
assert method() == 30

Booleanテスト(Groovy Truth)

実行時の真 判定される値 実行時の真 判定される値
Boolean 値がtrue String、GString 文字列が空ではない
Matcher マッチする Number、Character 値がゼロではない
Collection コレクションが空ではない 上記以外 参照がnullではない
Map マップが空ではない
Boolean値は自明
Copy
assert true
assert !false
Matcherはマッチすること
Copy
assert ('a' =~ /./)
assert !('a' =~ /b/)
コレクションは空ではないこと
Copy
assert [1]
assert ![]
マップは空ではないこと
Copy
assert ['a': 1]
assert ![:]
文字列は空ではないこと
Copy
assert 'a'
assert !''
数値(どの型も)はゼロではないこと
Copy
assert 1
assert 1.1
assert 1.2f
assert 1.3g
assert 2L
assert 3G
assert !0
その他は、すべてnullではないこと
Copy
assert new Object()
assert !null

正規表現

Groovyは言語レベルで正規表現をサポートしています。

正規表現
Copy
assert '12345' =~ /\d+/
assert 'xxxxx' == '12345'.replaceAll(/\d/, 'x')
正規表現についてはここがとても参考になります。

リスト、マップ、範囲

リストは[]で囲み、カンマで区切ります。空リストは[]です。

リスト
Copy
def roman = ['', 'I', 'II', 'III', 'IV', 'V', 'VI', 'VII'] // ローマ数字のリスト
assert roman[4] == 'IV' // リストへのアクセス
roman[8] = 'VIII' // リストの拡大
assert roman.size() == 9

マップも[]で囲み、「キー:値」の形で内容を示し、カンマで区切ります。空マップは[:]です。

マップ
Copy
def http = [
  100 : 'CONTINUE',
  200 : 'OK',
  400 : 'BAD REQUEST' ]
assert http[200] == 'OK'
http[500] = 'INTERNAL SERVER ERROR'
assert http.size() == 4

範囲は「a..b」や「a..<b」を使います。..の方は、後ろを含み、..<の方は後ろを含みません。

ここにタイトル
Copy
def x = 1..10
assert x.contains(5)
assert x.contains(15) == false
assert x.size() == 10
assert x.from == 1
assert x.to == 10
assert x.reverse() == 10..1
def y = 1..<10
assert y.from == 1
assert y.to == 9

クロージャ

ここにタイトル
Copy
[1, 2, 3].each { entry -> println entry }
[4, 5, 6].each { println it } // パラメータ省略時はitで参照できる
[a: 100, b: 200, c: 300].each { key, value ->
  println "${key}=${value}"
}
このあたりのもうちょっと詳しいサンプルはこのあたりでどうぞ。

4. クラス

暗黙的インポート

Groovyでは以下のパッケージが暗黙的にインポート済みです。

暗黙的インポート
Copy
java.io.*
java.lang.*
java.math.BigDecimal
java.math.BigInteger
java.net.*
java.util.*
groovy.lang.*
groovy.util.*

クラス宣言

クラス
Copy
class Book {    // クラスを宣言
  String title  // 型を明示的に指定してフィールドを宣言
  def prop      // defキーワードでフィールド宣言
  Book() {      // コンストラクタ
    // ...
  }
  int methodA(int p) { // 型を明示的に指定してメソッドを宣言
    // ...
  }
  void methodB(String p) { // 戻り値なしメソッド
    // ...
  }
  def methodC(p) { // defを使ってメソッドを宣言
    // ...
  }
  static def methodS() { // 静的メソッドを宣言
    // ...
  }
}

GroovyBean

GroovyではJavaよりも簡単にbeanを扱えます。

GroovyBean
Copy
class Book {
  String title  // プロパティの宣言
}
def groovyBook = new Book()

// 明示的なメソッド呼び出しによるプロパティの利用
groovyBook.setTitle('Groovy world')
assert groovyBook.getTitle() == 'Groovy world'

// Groovyによるショートカットを使ったプロパティの利用
groovyBook.title = 'No Groovy, No Life'
assert groovyBook.title == 'No Groovy, No Life'

まだまだ紹介しきれないので、ちょこちょこ追加していく予定です。


参考

元記事

参考書籍

Groovy公式サイト

関連記事

参考サイト


  1. いわゆるヒアドキュメント ↩︎

  2. こちらで無理やりdo-whileを実装する実験をしました。 ↩︎