お題
Javaでは例えば↓のように、いわゆるJavaBeansを作ると、フィールドの数に応じてけっこうなコード量になる。
public class Book {
private int id;
private String name;
private int price;
private String publishDate;
public Book() {
}
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;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
public String getPublishDate() {
return publishDate;
}
public void setPublishDate(String publishDate) {
this.publishDate = publishDate;
}
@Override
public String toString() {
return "Book{" +
"id=" + id +
", name='" + name + '\'' +
", price=" + price +
", publishDate='" + publishDate + '\'' +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Book book = (Book) o;
return id == book.id &&
price == book.price &&
Objects.equals(name, book.name) &&
Objects.equals(publishDate, book.publishDate);
}
@Override
public int hashCode() {
return Objects.hash(id, name, price, publishDate);
}
}
これが、Lombokを使うと、↓のように書くだけで↑と同じメソッドを持つコードになる。
import lombok.Data;
@Data
public class Book {
private int id;
private String name;
private int price;
private String publishDate;
}
便利なので、少し調べてみることにする。
開発環境
# OS
$ cat /etc/os-release
NAME="Ubuntu"
VERSION="17.10 (Artful Aardvark)"
# Java
$ java -version
java version "1.8.0_181"
Java(TM) SE Runtime Environment (build 1.8.0_181-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.181-b13, mixed mode)
# IDE
みんな大好きIntelliJ IDEA
実践
導入手順
Mavenプロジェクト生成
mvn -B archetype:generate -DarchetypeGroupId=org.apache.maven.archetypes -DgroupId=com.example -DartifactId=try-java-lombok
pom.xml にLombokを追加
<dependencies>
〜〜〜
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.4</version>
<scope>provided</scope>
</dependency>
</dependencies>
IntelliJにLombokプラグイン追加
Lombokによりどのようなコードになるかを確認するためJarをダウンロード
各アノテーションを試す
全ソースは↓
https://github.com/sky0621/try-java-lombok
@Getter
と@Setter
その名の通り、変数に付加するとゲッターセッターを自動生成。
【Lombokアノテーション付与ソース】
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class GetterSetter {
private String text;
}
【実行時のソース】
public class GetterSetter {
private String text;
@java.lang.SuppressWarnings("all")
public String getText() {
return this.text;
}
@java.lang.SuppressWarnings("all")
public void setText(final String text) {
this.text = text;
}
}
@ToString
その名の通り。
【Lombokアノテーション付与ソース】
@lombok.ToString
public class ToString {
private String text;
}
【実行時のソース】
public class ToString {
private String text;
@java.lang.Override
@java.lang.SuppressWarnings("all")
public java.lang.String toString() {
return "ToString(text=" + this.text + ")";
}
}
@EqualsAndHashCode
「equals」メソッド及び「hashCode」メソッド生成。
【Lombokアノテーション付与ソース】
@lombok.EqualsAndHashCode
public class EqualsAndHashCode {
private String text;
}
【実行時のソース】
public class EqualsAndHashCode {
private String text;
@java.lang.Override
@java.lang.SuppressWarnings("all")
public boolean equals(final java.lang.Object o) {
if (o == this) return true;
if (!(o instanceof EqualsAndHashCode)) return false;
final EqualsAndHashCode other = (EqualsAndHashCode) o;
if (!other.canEqual((java.lang.Object) this)) return false;
final java.lang.Object this$text = this.text;
final java.lang.Object other$text = other.text;
if (this$text == null ? other$text != null : !this$text.equals(other$text)) return false;
return true;
}
@java.lang.SuppressWarnings("all")
protected boolean canEqual(final java.lang.Object other) {
return other instanceof EqualsAndHashCode;
}
@java.lang.Override
@java.lang.SuppressWarnings("all")
public int hashCode() {
final int PRIME = 59;
int result = 1;
final java.lang.Object $text = this.text;
result = result * PRIME + ($text == null ? 43 : $text.hashCode());
return result;
}
}
@NoArgsConstructor
引数なしコンストラクタを生成
【Lombokアノテーション付与ソース】
@lombok.NoArgsConstructor
public class NoArgsConstructor {
}
【実行時のソース】
public class NoArgsConstructor {
@java.lang.SuppressWarnings("all")
public NoArgsConstructor() {
}
}
@AllArgsConstructor
全引数指定コンストラクタを生成
【Lombokアノテーション付与ソース】
@lombok.AllArgsConstructor
public class AllArgsConstructor {
private int id;
private String name;
private Date created;
}
【実行時のソース】
public class AllArgsConstructor {
private int id;
private String name;
private Date created;
@java.lang.SuppressWarnings("all")
public AllArgsConstructor(final int id, final String name, final Date created) {
this.id = id;
this.name = name;
this.created = created;
}
}
@RequiredArgsConstructor
特別な処理が必要なフィールドごとに1つのパラメータを持つコンストラクタを生成
【Lombokアノテーション付与ソース】
@lombok.RequiredArgsConstructor
public class RequiredArgsConstructor {
@NonNull
private int id;
@NonNull
private String text;
private Data created;
}
【実行時のソース】
import lombok.Data;
import lombok.NonNull;
public class RequiredArgsConstructor {
@NonNull
private int id;
@NonNull
private String text;
private Data created;
@java.lang.SuppressWarnings("all")
public RequiredArgsConstructor(@NonNull final int id, @NonNull final String text) {
if (text == null) {
throw new java.lang.NullPointerException("text is marked @NonNull but is null");
}
this.id = id;
this.text = text;
}
}
@Data
上記までで紹介したアノテーションのうち、一挙に@ToString
、@EqualsAndHashCode
、@Getter
を全フィールドに付与し、@Setter
を全てのfinal
フィールドに付与。あと、@RequiredArgsConstructor
も付与。
【Lombokアノテーション付与ソース】
@lombok.Data
public class Data {
private int id;
private String name;
private int price;
private String publishDate;
}
【実行時のソース】
public class Data {
private int id;
private String name;
private int price;
private String publishDate;
@java.lang.SuppressWarnings("all")
public Data() {
}
@java.lang.SuppressWarnings("all")
public int getId() {
return this.id;
}
@java.lang.SuppressWarnings("all")
public String getName() {
return this.name;
}
@java.lang.SuppressWarnings("all")
public int getPrice() {
return this.price;
}
@java.lang.SuppressWarnings("all")
public String getPublishDate() {
return this.publishDate;
}
@java.lang.SuppressWarnings("all")
public void setId(final int id) {
this.id = id;
}
@java.lang.SuppressWarnings("all")
public void setName(final String name) {
this.name = name;
}
@java.lang.SuppressWarnings("all")
public void setPrice(final int price) {
this.price = price;
}
@java.lang.SuppressWarnings("all")
public void setPublishDate(final String publishDate) {
this.publishDate = publishDate;
}
@java.lang.Override
@java.lang.SuppressWarnings("all")
public boolean equals(final java.lang.Object o) {
if (o == this) return true;
if (!(o instanceof Data)) return false;
final Data other = (Data) o;
if (!other.canEqual((java.lang.Object) this)) return false;
if (this.getId() != other.getId()) return false;
final java.lang.Object this$name = this.getName();
final java.lang.Object other$name = other.getName();
if (this$name == null ? other$name != null : !this$name.equals(other$name)) return false;
if (this.getPrice() != other.getPrice()) return false;
final java.lang.Object this$publishDate = this.getPublishDate();
final java.lang.Object other$publishDate = other.getPublishDate();
if (this$publishDate == null ? other$publishDate != null : !this$publishDate.equals(other$publishDate)) return false;
return true;
}
@java.lang.SuppressWarnings("all")
protected boolean canEqual(final java.lang.Object other) {
return other instanceof Data;
}
@java.lang.Override
@java.lang.SuppressWarnings("all")
public int hashCode() {
final int PRIME = 59;
int result = 1;
result = result * PRIME + this.getId();
final java.lang.Object $name = this.getName();
result = result * PRIME + ($name == null ? 43 : $name.hashCode());
result = result * PRIME + this.getPrice();
final java.lang.Object $publishDate = this.getPublishDate();
result = result * PRIME + ($publishDate == null ? 43 : $publishDate.hashCode());
return result;
}
@java.lang.Override
@java.lang.SuppressWarnings("all")
public java.lang.String toString() {
return "Data(id=" + this.getId() + ", name=" + this.getName() + ", price=" + this.getPrice() + ", publishDate=" + this.getPublishDate() + ")";
}
}
まとめ
まだまだ便利アノテーションはあるのだけど、今日は時間切れ。
残りは、また後日。