当メモは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)
print 'Hello, Groovy!!' // 改行なし println 'Hello, Groovy!!' // 改行あり printf 'Hello, %s', 'Groovy!!' // 整形して表示
コメント
// 一行コメント /* 複数行コメント */ /** Groovydoc(Javadoc)コメント */
Groovydoc
についてはこちら。
括弧やセミコロンの省略
Groovyではコードの解釈に支障がない場合に限り、括弧やセミコロンの省略が可能です。
println("hi"); println("hi") println "hi"
- 上記はすべて同じ意味となります。
アサーション
Groovyではどこでもassert文
を利用できます。
コード内にassertテストを埋め込んでコードの正当性を保つのがGroovyのスタイルです。
assert 式, コメント
- 上記のような形式で利用できます。
- コメントは省略可能です。
def a = 10 def b = 20 assert 30 == a + b, '足したら30のはず'
- 式が真の間は実行しても何も起こりませんが、偽の場合はエラーとなります。
- assert文が文に埋め込まれているおかげで、その時点での変数などの状態の正当性が主張できるわけです。
以降、サンプルコードでもassert文
を利用します。
等値性と同一性
#equals()
は==
、==
は#is()
。
分かりにくいので、Javaと比較すると以下のようになります。
Groovy | Java | |
---|---|---|
等値性 | a == b | a.equals(b) |
同一性 | a.is(b) | a == b |
また、nullに対してもチェック可能です。
assert null == null assert !(null == 1)
2. データ型
すべてがObject(プリミティブはない)
1
、 1.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キーワードはどんな型でもよいということを示すために使われます。
明示的に型を指定してもよいです。
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 (参照型の型名を使った明示的な型付け)
int
やfloat
などはjava.lang.Integer
やjava.lang.Float
のエイリアスです。
演算子のオーバーライド
たとえば、1 + 1
は 1.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
と等価です。
def str = 'シングルクォート'
ダブルクォート文字列
2つ目はダブルクォートを用いるものです。こちらは以下のように変数($
の後に変数名)や式を埋め込むことができます。groovy.lang.GString
と等価です。
def a = 'world' def str1 = "hello $a" def str2 = "hello ${a}" assert str1 == str2 assert str1 == 'hello world'
スラッシュ文字列
3つ目はスラッシュ/
を用いるものです。こちらはバックスラッシュ\
をエスケープせずに利用できるため、正規表現を埋め込む際に利用されます。それ以外はダブルクォートのものと同様です。
def pathStr = /C:\temp\xxxx/ // バックスラッシュがそのまま使える def regexpStr = /^\d{4}-\d{3}/ // 正規表現を宣言する時に便利 def color = 'blue' def interpolatedSlashy = /a ${color} car/ // 変数埋め込みも可能
- 注意が必要なのはスラッシュ文字列中で、
$
をエスケープできない点です。$
をエスケープしたい場合は、以下のドルスラッシュ文字列を利用します。
ドルスラッシュ文字列
4つ目はドルスラッシュ$/
と/$
を用いるものです。基本的にはスラッシュ文字列と同じなのですが、文字列中のエスケープ文字が\
ではなく、$
になったものです。
def pathStr = $/C:\temp\xxxx/$ // バックスラッシュがそのまま使える def regexpStr = $/^\d{4}-\d{3}/$ // 正規表現を宣言する時に便利 def color = 'blue' def interpolatedSlashy = $/a ${color} car/$ // 変数埋め込みも可能 def interpolatedSlashy2 = $/a $${color} car/$ // $でエスケープも可能
- 最後のinterpolatedSlashy2の例の
$${color}
の部分は${color}
という文字列になります。($
でエスケープできる)
複数行文字列
上記4つの文字列の複数行文字列1もリテラルレベルでサポートされています。
シングルクォートとダブルクォートはそれぞれ3つにすることで複数行文字列として利用可能です。
スラッシュ文字列とドルスラッシュ文字列は最初から複数行文字列として利用可能です。
// シングルクォート文字列の複数バージョン 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行に複数の文を記述することができます。
文1 文2
文1; 文2
制御構造
if-else
if (false) assert false
if (null) { assert false } else { assert true }
while
def i = 0 while (i < 10) { i++ } assert i == 10
do
Groovyにdoはありません。2
for
for (i = 0; i < 10; i++) { println i }
def clinks = 0 for (remainingGuests in 0..9) { clinks += remainingGuests }
def list = [0, 1, 2, 3, 4, 5] for (j in list) { assert j == list[j] }
switch
switch(3) { case 1 : assert false; break case 3 : assert true; break default: assert false }
try-catch-finally
try { // 処理 } catch(e) { // 例外e発生時処理 } finally { // 最終処理 }
return/break/continue
return
, break
, continue
の一般的なロジックはJavaと同じです。
ただし、Groovyではreturn
が省略可能です。省略した場合、最後に評価された値が返却されます。
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 | マップが空ではない |
assert true assert !false
assert ('a' =~ /./) assert !('a' =~ /b/)
assert [1] assert ![]
assert ['a': 1] assert ![:]
assert 'a' assert !''
assert 1 assert 1.1 assert 1.2f assert 1.3g assert 2L assert 3G assert !0
assert new Object() assert !null
正規表現
Groovyは言語レベルで正規表現をサポートしています。
assert '12345' =~ /\d+/ assert 'xxxxx' == '12345'.replaceAll(/\d/, 'x')
リスト、マップ、範囲
リストは[]
で囲み、カンマで区切ります。空リストは[]
です。
def roman = ['', 'I', 'II', 'III', 'IV', 'V', 'VI', 'VII'] // ローマ数字のリスト assert roman[4] == 'IV' // リストへのアクセス roman[8] = 'VIII' // リストの拡大 assert roman.size() == 9
マップも[]
で囲み、「キー:値」
の形で内容を示し、カンマで区切ります。空マップは[:]
です。
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
」を使います。..
の方は、後ろを含み、..<
の方は後ろを含みません。
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
クロージャ
[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では以下のパッケージが暗黙的にインポート済みです。
java.io.* java.lang.* java.math.BigDecimal java.math.BigInteger java.net.* java.util.* groovy.lang.* groovy.util.*
クラス宣言
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を扱えます。
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公式サイト
- Apache Groovy
- (Apache Groovy) groovydoc, the Groovy & Java documentation generator
- (Apache Groovy) Syntax
- Groovy JDK API Documentation
関連記事
- (No Programming, No Life) JavaからGroovyへ移行する簡単なステップ
- (No Programming, No Life) Groovyのヒアドキュメントで改行取り消し
- (No Programming, No Life) Groovyでdo-whileループを!
- Groovyのチートシート
- (No Programming, No Life) Scalaも素晴らしいけど、Groovyも素晴らしいですよ