こんにちは。SI部の満石です。
今回はJava特有の冗長なコードを簡潔にしてくれる「Lombok」を紹介します。
はじめに
Javaエンジニアの方なら、一度はEclipseの機能を使用してsetter/getterの自動生成や、hashCode()、equals()、toString()の生成を行ったことがあると思います。
Eclipseのこの機能は便利ですが、自動で生成できるようなアプリケーションの本質とは関係のない冗長なコードが必要になってしまっていると言えます。
また、フィールドの追加・削除・変更を行う場合は自動生成し直す必要があり面倒です。
フィールドを追加の場合はhashCode()、equals()、toString()は自動生成しなおさなくてもエラーとならないため、自動生成を忘れるとバグの原因にもなります。
このようなことはこれまでは仕方がないことだと受け入れてきたのではないでしょうか?
Lombokとは
Lombokとは、Java特有の冗長なコードを簡潔にしてくれるオープンソースのライブラリです。
ライセンスはMITライセンスなので自由に利用することが出来ます。
LombokはEclipseの自動生成機能の代わりにアノテーションを使うことで冗長なコードを簡潔にします。
インストール
Project Lombokのサイトから、lombok.jarをダウンロードします。
執筆時点のバージョンは1.12.6です。
LombokはIDEとしてEclipseとNetBeansをサポートしていて、IntelliJ IDEAもプラグインが存在するようです。
詳しくはLombokのダウンロードページを参照してください。
今回はIDEとしてEclipseを使用します。
lombok.jarをダブルクリックするとインストーラーが起動し、インストールされているEclipseを検出します。
Lombokを利用したいEclipseを選択して、「Install / Update」ボタンをクリックします。
以下のメッセージがポップアップします。
インストール対象のEclipseが存在するフォルダを確認するとlombok.jarがコピーされていて、
eclipse.iniファイルには以下の2行が追加されていることが確認できました。
-javaagent:lombok.jar
-Xbootclasspath/a:lombok.jar
インストーラーを使わない場合はlombok.jarをEclipseが存在するフォルダにコピーし、この2行をeclipse.iniに追加すれば良さそうです。
次に、メッセージにあるとおりEclipseを起動し、lombok.jarをプロジェクトのクラスパスに追加します。
プロジェクトを右クリックし、「プロパティー」→「Javaのビルドパス」と選択し、「ライブラリー」タブでlombok.jarをビルドパスに追加します。
以上でLombokを使用する準備が整いました。
@Data
まず@Dataの使い方から紹介します。
以下のMemberクラスはid、nameの2つのフィールドがあり、setter/getter、hashCode()、equals()、toString()をEclipseの自動生成機能で作成したものです。
非常に冗長ですね。
public class Member { private int id; private String name; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + id; result = prime * result + ((name == null) ? 0 : name.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Member other = (Member) obj; if (id != other.id) return false; if (name == null) { if (other.name != null) return false; } else if (!name.equals(other.name)) return false; return true; } @Override public String toString() { return "Member [id=" + id + ", name=" + name + "]"; } }
このクラスをLombokの@Dataを使用して書き換えると以下のようになります。
import lombok.Data; @Data public class Member { private int id; private String name; }
なんとsetter/getter、hashCode()、equals()、toString()が無くなってスッキリしました!
ではこれらのメソッドはどうなったのでしょうか?
Eclipseの「アウトライン」ビューを見てみると、以下のように表示されています。
コードとしてはidとnameの2つのフィールドしか無いはずが、getter/setter、hashCode()、equals()、toString()に加えて、引数なしのコンストラクタとcanEqual()というメソッドが存在することになっています。実はこれらはコンパイル時に自動生成されています。canEqual()はinstanceof演算子による比較結果を返すようです。
@Getterと@Setter
フィールドによってはsetterのみ、またはgetterのみとしたいことがあります。そのような場合には@Getterと@Setterを利用します。
@Dataはクラスに付与しましたが、@Getterと@Setterはフィールドに対して付与します。
先ほどのMemberクラスから@Dataを削除して、idに@Getter、nameに@Setterを付与してみましょう。
import lombok.Getter; import lombok.Setter; public class Member { @Getter private int id; @Setter private String name; }
Eclipseの「アウトライン」ビューは、以下のようになります。
idはgetterのみが、nameにはsetterのみが生成されていることが確認できました。
@AllArgsConstructor
すべてのフィールドを引数に持つコンストラクタを自動生成したい場合は@AllArgsConstructorを使用します。
import lombok.AllArgsConstructor; @AllArgsConstructor public class Member { private int id; private String name; }
Eclipseの「アウトライン」ビューは、以下のようになります。
idとnameが引数のコンストラクタが生成されていることが確認できました。
@Dataと併用することも出来ます。
import lombok.AllArgsConstructor; import lombok.Data; @Data @AllArgsConstructor public class Member { private int id; private String name; }
Eclipseの「アウトライン」ビューは、以下のようになります。
@Dataだけだと引数なしのコンストラクタが生成されていましたが、@AllArgsConstructorも付与することで代わりにidとnameが引数のコンストラクタが作成されました。
@NoArgsConstructor
@Dataと@AllArgsConstructorを併用する場合、引数なしのコンストラクタは生成されなくなりました。しかし、デフォルトコンストラクタも必要な場合があります。その場合は@NoArgsConstructorをさらに付与します。
import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @Data @AllArgsConstructor @NoArgsConstructor public class Member { private int id; private String name; }
Eclipseの「アウトライン」ビューは、以下のようになります。
今度は引数なしのデフォルトコンストラクタと引数ありのコンストラクタの両方が生成されました。
@EqualsAndHashCode
equals()とhashCode()を自動生成する場合は@EqualsAndHashCodeを使用します。
import lombok.EqualsAndHashCode; @EqualsAndHashCode public class Member { private int id; private String name; }
Eclipseの「アウトライン」ビューは、以下のようになります。
equals()とhashCode()に加えて、@Dataと同様にcanEqual()メソッドも追加されました。
@toString
toString()を自動生成する場合は@toStringを使用します。
import lombok.ToString; @ToString public class Member { private int id; private String name; }
Eclipseの「アウトライン」ビューは、以下のようになります。
toString()が自動生成されていることが確認できました。
さいごに
今回はLombokの代表的なアノテーションを紹介しましたが、他にも@SneakyThrows、@Delegate、@Cleanupや、動的に型を決定できるvalという型が使える等、面白い機能が用意されています。どんなJavaプロジェクトでも利用可能なのでぜひ導入を検討してみてください!