面倒くさがり屋なJavaエンジニアのためのGroovy入門

# 目次
- Groovyとは
- Groovyの特徴
    - Groovyのメリット
    - Groovyのデメリット
- おわりに

---

# Groovyとは
**JVM上で動作する、動的型付けスクリプト言語**

---

#Groovyの特徴
なぜ、"面倒くさがり屋な" "Javaエンジニア" を対象にするのか...

それはGroovyには次のようなメリットがあるから。

**1.Javaに比べてコード量が少なく済む**
2.JavaのAPIも利用できる
3.充実したエコシステム(WebアプリケーションフレームワークのGrails、テスティングフレームワークのSpockなど)

---

## Groovyのメリット - Javaに比べてコード量が少なく済む

- 変数宣言/メソッド宣言

`def`で変数宣言ができる(型を明示することもできる)
`def`で宣言した場合、変数の型は`Object型`
publicメソッド宣言時に`public`は不要(メソッドのスコープはデフォルトでpublicのため)

```Java:Java
String helloWorld = "Hello World.";

public static void main(String[] args) {
    // do something
}
```

```Groovy:Groovy
def helloWorld = "Hello World."

//publicは省略可
static void main(String[] args) {
    // do something
}

// 戻り値の型はdefでもOK
static def main(String[] args) {
    //do something
}

// 戻り値の型は省略可
static main(String[] args) {
    //do something
}

// 引数の型も省略可
static main(args) {
    //do something
}
```

---

- 文字列

`$変数`の形で、変数を文字列に埋め込める

```Java:Java
String name = "Michael";
System.out.println("Hello " + name + "!");

// 出力結果
// Hello Michael!
```

```Groovy:Groovy
def name = "Michael"
println "Hello $name!"

// 出力結果
// Hello Michael!
```

---

- List, Mapの初期化

Listの初期化は`[]`
Mapの初期化は`[:]`

```Java:Java
List<String> list = new ArrayList<>();
Map<String, String> map = new HashMap<>();
```

```Groovy:Groovy
def list = []
def map = [:] // 型はLinkedhashMapになる
```

---

- コレクションの操作

クロージャーが便利
`it`はクロージャーに渡される引数を表す暗黙の変数(下の例では`numbers`リストの1つ1つの要素)

```Java:Java
List<Integer> numbers = List.of(1, 2, 3, 4, 5);
List<Integer> odds = numbers.stream().filter(number -> number % 2 != 0).collect(Collectors.toList());
System.out.println(odds);

// 出力結果
// [1, 3, 5]
```

```Groovy:Groovy
def numbers = [1, 2, 3, 4, 5] 
def odds = numbers.findAll { it % 2 != 0 } 
// この書き方でもOK
// def odds = numbers.findAll { number -> number % 2 != 0 }
println odds

// 出力結果
// [1, 3, 5]
```

---

- DB操作(MySQL)

`@Grab`でGrapeという構成管理ツールを使用して外部リポジトリ(Mavenリポジトリなど)からライブラリを取得できる
`groovy.sql.Sql`クラスが便利

personテーブル

| person_id | first_name | last_name |
|:---------:|:----------:|:---------:|
| 1         | Michael    | Jordan    |
| 2         | Michael    | Jackson   |

```Java:Java
// mysql-connector-javaをダウンロードし、クラスパスに追加

Class.forName("com.mysql.jdbc.Driver");
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/sampledb", "root", "root");
// first_nameがMichaelのレコードのlast_nameを取得
PreparedStatement pstmt = conn.prepareStatement("SELECT last_name FROM person WHERE first_name = ?");
pstmt.setString(1, "Michael");
ResultSet rs = pstmt.executeQuery();
// 取得したレコードのlast_nameをコンソールに出力
while(rs.next()) {
    System.out.println(rs.getString("last_name"));
}

// 出力結果
// "Jordan"
// "Jackson"
```

```Groovy:Groovy
// Grapeを使用して外部リポジトリからmysql-connector-javaを取得
@GrabConfig(systemClassLoader=true)
@Grab("mysql:mysql-connector-java:5.1.49")

def sql = Sql.newInstance("jdbc:mysql://localhost:3306/sampledb", "root", "root", "com.mysql.jdbc.Driver")
// first_nameがMichaelのレコードのlast_nameを取得
def rows = sql.rows("SELECT last_name FROM person WHERE first_name = ?", ["Michael"])
// 取得したレコードのlast_nameをコンソールに出力
rows.each {
    println it.last_name
}

// 出力結果
// "Jordan"
// "Jackson"
```

---

# Groovyのデメリット

- コンパイル時に型チェックができない
 
動的型付け言語であるため、型を宣言せず、`def`で宣言した変数やクロージャーの引数については実行時に型チェックがされるため、型が原因のエラーについては実行時まで指摘されない。

- バージョンによってはJavaの構文が一部サポートされていない

try-with-resource文やラムダ式等の一部の構文について、2系ではサポートされていない。
バージョン3系ではこれらもサポートされているが、リリースされたのが今年の2月のため、Groovyを使用するフレームワークやライブラリについては最新バージョンでも2.5系を使っている可能性がある。

---

# おわりに

GroovyはJavaに比べてコード量が少なく済み、開発効率のアップにつながることが期待できます。
また、Javaエンジニアにとっては学習コストは低く、習得までさほど時間はかからないでしょう。(私も3か月ほどで習得できました。)
もしJavaのコードを冗長に感じていたり、より効率的に開発したいと思っていたりするようなら、Groovyを試してみてはいかがでしょうか？

---