Lombokの@Data(lombok.Data)アノテーションの利用サンプルです。
クラスに@Data
アノテーションを付与すると、対象クラス内のインスタンス変数に対してgetter/setterでアクセスすることが可能となります。
対象のインスタンス変数をfinalで宣言している場合は、finalのメンバを引数に取るコンストラクタとgetterが使用可能となります。
@Data
アノテーションを付与すると、@Getter
/@Setter
, @ToString
, @EqualsAndHashCode
, @RequiredArgsConstructor
を付与したのと同じ状態となります
@Dataアノテーションを付与したクラスの動きの確認
@Data
アノテーションをパラメータの指定なしでクラスに付与します
■@Dataアノテーションを付与したクラス
import lombok.Data; @Data public class Person1 { private long id; private String name; private int age; private boolean isAdult; }
■利用側のコード
サンプルコードでは以下の確認をしています
- getterが使える
- setterが使える
- hashCodeがオーバーライドされている
- toStringがオーバーライドされている
- equalsがオーバーライドされている
public class Person1Client { public static void main(String[] args) { Person1 p1 = new Person1(); // 対象クラスでsetterを記述してないのにsetterが使える p1.setId(100); p1.setName("Taro"); p1.setAge(12); p1.setAdult(true); // 対象クラスでgetterを記述してないのにgetterが使える System.out.println("id: " + p1.getId()); System.out.println("name: " + p1.getName()); System.out.println("age: " + p1.getAge()); System.out.println("isAdulet: " + p1.isAdult()); // hashCodeも自動生成されている System.out.println("p1#hashCode: " + p1.hashCode()); System.out.println("-------------"); // メンバに同じ値を指定すればhashCodeは同じ値を返す Person1 p2 = new Person1(); p2.setId(100); p2.setName("Taro"); p2.setAge(12); p2.setAdult(true); System.out.println("p1#hashCode: " + p1.hashCode()); System.out.println("p2#hashCode: " + p2.hashCode()); Person1 p3 = new Person1(); p3.setId(100); p3.setName("Taro"); p3.setAge(12); p3.setAdult(true); System.out.println("p3#hashCode: " + p3.hashCode()); Person1 p4 = new Person1(); p4.setId(100); p4.setName("Taro"); p4.setAge(12); p4.setAdult(false); System.out.println("p4#hashCode: " + p4.hashCode()); System.out.println("-------------"); // toStringの内容確認 System.out.println("p1#toString: " + p1); System.out.println("p2#toString: " + p2); System.out.println("p3#toString: " + p3); System.out.println("p4#toString: " + p4); System.out.println("-------------"); // equalsも自動生成されている System.out.println("p1 eqauls p1 -> " + p1.equals(p1)); System.out.println("p1 eqauls p2 -> " + p1.equals(p2)); System.out.println("p1 eqauls p3 -> " + p1.equals(p3)); System.out.println("p1 eqauls p3 -> " + p1.equals(p4)); System.out.println("p2 eqauls p3 -> " + p2.equals(p3)); System.out.println("p2 eqauls p4 -> " + p2.equals(p4)); System.out.println("p3 eqauls p4 -> " + p3.equals(p4)); } }
■実行結果
id: 100 name: Taro age: 12 isAdulet: true p1#hashCode: 490905642 ------------- p1#hashCode: 490905642 p2#hashCode: 490905642 p3#hashCode: 490905642 p4#hashCode: 490905660 ------------- p1#toString: Person1(id=100, name=Taro, age=12, isAdult=true) p2#toString: Person1(id=100, name=Taro, age=12, isAdult=true) p3#toString: Person1(id=100, name=Taro, age=12, isAdult=true) p4#toString: Person1(id=100, name=Taro, age=12, isAdult=false) ------------- p1 eqauls p1 -> true p1 eqauls p2 -> true p1 eqauls p3 -> true p1 eqauls p3 -> false p2 eqauls p3 -> true p2 eqauls p4 -> false p3 eqauls p4 -> false
■実際生成されているソースコード
実際に生成されているソースコードをdelombokを使って確認してみました
public class Person1 { private long id; private String name; private int age; private boolean isAdult; public Person1() { } public long getId() { return this.id; } public String getName() { return this.name; } public int getAge() { return this.age; } public boolean isAdult() { return this.isAdult; } public void setId(final long id) { this.id = id; } public void setName(final String name) { this.name = name; } public void setAge(final int age) { this.age = age; } public void setAdult(final boolean isAdult) { this.isAdult = isAdult; } @Override public boolean equals(final Object o) { if (o == this) return true; if (!(o instanceof Person1)) return false; final Person1 other = (Person1) o; if (!other.canEqual((Object) this)) return false; if (this.getId() != other.getId()) return false; final Object this$name = this.getName(); final Object other$name = other.getName(); if (this$name == null ? other$name != null : !this$name.equals(other$name)) return false; if (this.getAge() != other.getAge()) return false; if (this.isAdult() != other.isAdult()) return false; return true; } protected boolean canEqual(final Object other) { return other instanceof Person1; } @Override public int hashCode() { final int PRIME = 59; int result = 1; final long $id = this.getId(); result = result * PRIME + (int) ($id >>> 32 ^ $id); final Object $name = this.getName(); result = result * PRIME + ($name == null ? 43 : $name.hashCode()); result = result * PRIME + this.getAge(); result = result * PRIME + (this.isAdult() ? 79 : 97); return result; } @Override public String toString() { return "Person1(id=" + this.getId() + ", name=" + this.getName() + ", age=" + this.getAge() + ", isAdult=" + this.isAdult() + ")"; } }
@Dataを付与したクラスにfinalフィールドがある場合
対象クラスに@Data
アノテーションを付与していて、そのクラスにfinalフィールドが存在していると、
自動的にfinalフィールドをセットするための引数付きコンストラクタが定義されます
■@Dataアノテーションを付与したクラス(一部のフィールドがfinal)
import lombok.Data; @Data // id は必須 public class Person4 { private final long id; private String name; private int age; }
■IDEでの表示状態
■利用側のコード
public class Person4Client { public static void main(String[] args) { long id = 5; // finalフィールドへの値を設定するための引数付きコンストラクタが定義される Person4 p = new Person4(id); p.setName("Sample Hanako"); p.setAge(24); // p.setId(100L); <-- finalフィールドへのsetterは定義されない System.out.println(p); // Person4 p2 = new Person4(); <-- デフォルトコンストラクタは定義されない } }
■実行結果
Person4(id=5, name=Sample Hanako, age=24)
staticファクトリメソッドを定義する
@Data
アノテーションに、staticConstructor
パタメータを指定することで、対象クラスのインスタンスを生成するためのファクトリメソッドを定義することができます
■@Dataアノテーションを付与したクラス
import lombok.Data; // ファクトリメソッドの名前を of とする @Data(staticConstructor="of") public class Person3 { private final long id; private String name; private int age; }
■利用側のコード
public class Person3Client { public static void main(String[] args) { long id = 101; Person3 p = Person3.of(id); // staticファクトリメソッドが定義されている p.setName("Taro"); p.setAge(12); // 対象クラスでgetterを記述してないのにgetterが使える System.out.println("Person3#toString: " + p); // Person3 p1 = new Person3(200); <-- コンストラクタの呼び出しはできない } }
■実行結果
Person3#toString: Person3(id=101, name=Taro, age=12)