Lombokが便利だなと感じたので書いてみた

# 現場で学んだことをまとめようシリーズ(はじめに)
そのまま、現場で学んだ(使用した)ツール等についてまとめていくシリーズです。
自分のためでもあり、それが誰かのためになればいいな、という気持ちを込めて書きます。
間違えや記述方法についての指摘やコメント、お待ちしております！

# Lombokってなんぞや？
アノテーションを付与することによって、Javaのボイラープレートコード[^1]を排除することができるライブラリです。
アノテーションを付けるだけで、**全てのフィールドに対してgetter、setterを実装**してくれたり、**コンストラクタを実装**してくれたりします！

データクラスの作成やコンストラクタインジェクションが楽になるので、**Spring-Bootと非常相性が良い**と個人的に思います！
イミュータブルなオブジェクト[^2]を使いたい時にも役立ちますので、
ぜひ使ってみてください！

ちなみに読み方は`ロンボック`または`ロンボク`のようです。私は`ロンボック`派です。

# アノテーションの説明・使い方
ここからは各アノテーションについて説明していきます。

## Getter、Setter
クラス、またはフィールドに`@Getter`、`@Setter`を付与するとgetter、setterを実装できます。
例えば以下のような`Sample.java`を実装したとします。

``` java:Sample.java
@Getter
@Setter
public class Sample {
  private String id;
  private String name;
  private Integer age:
}
```

上記をコンパイルして`Sample.class`の中身を確認すると、以下のようになります。

``` java:Sample.class
public class Sample {
  private String id;
  private String name;
  private Integer age:

  public String getId() {
    return this.id;
  }

  public String getName() {
    return this.name;
  }

  public Integer getAge() {
    return this.name;
  }

  public void setId(String id) {
    this.id = id;
  }

  public void setName(String name) {
    this.name = name;
  }

  public void setAge(Integer age) {
    this.age = age;
  }
}
```
…見事に全てのフィールドに対してgetterとsetterが実装されていますね。
フィールドが多ければ多いほど記述量を削減できます！

この例ではclassに対して付与していますが、
全フィールドに対して付与したくない場合はフィールドごとに付与しましょう！

## 〇〇ArgsConstructor(コンストラクタ)
こちらは付与するだけでコンストラクタを自動生成してくれるアノテーションです。三種類あります。

* `@NoArgsConstructor` … デフォルトコンストラクタを自動生成します。
* `@AllArgsConstructor` … 全フィールドに対する初期化値を引数にとるコンストラクタを生成します。
* `@RequiredArgsConstructor` … finalフィールドに対しる初期化値を引数にとるコンストラクタを生成します。

### RequiredArgsConstructor
実装した`Sample.java`が以下だとすると、

``` java:Sample.java
@RequiredArgsConstructor
public class Sample {
  private final String id;
  private final String name;
  private Integer age;
}
```

以下のような`Sample.class`が作られます。

``` java:Sample.class
public class Sample {
  private final String id;
  private final String name;
  private Integer age;

  public Sample(String id, String name) {
    this.id = id;
    this.name = name;
  }
}
```

### NoArgsConstructor + AllArgsConstructor
複数付与すればそれだけコンストラクタを生成してくれます。
javaの仕様上、明確にコンストラクタを実装していまうとデフォルトコンストラクタは実装されませんので、
`@NoArgsConstructor`も結構出番があります。

``` java:Sample.java
@NoArgsConstructor
@AllArgsConstructor
public class Sample {
  private String id;
  private String name;
  private Integer age;
}
```

``` java:Sample.class
public class Sample {
  private String id;
  private String name;
  private Integer age;

  public Sample() {
  };

  public Sample (String id, String name, Integer age) {
    this.id = id;
    this.name = name;
    this.age = age;
  }
}
```

この組み合わせは[MyBatisのEntityクラス](https://qiita.com/supreme0110/items/ce31a506185ccc97693f)と相性がいいです。

## ToString
`@ToString`はその名の通り、`toString`を実装(オーバーライド)してくれます。
また`exclude`を使用すると対象のフィールドを除外することが可能です。

``` java:Sample.java
@ToString(exclude = "age")
public class Sample {
  private String id;
  private String name;
  private Integer age;
}
```

``` java:Sample.class
public class Sample {
  private String id;
  private String name;
  private Integer age;

  @Override
  public String toString() {
    return "Sample(id=" + this.id + ", name=" + this.name + ")");
  }
}
```

## EqualsAndHashCode
`@EqualsAndHashCode`もその名の通り、`equals`と`hashCode`が実装(オーバーライド)されます。
なぜこの二つはセットかというと、これらは[仕組み上で関係しており矛盾してはならない](https://qiita.com/yoshi389111/items/9e34fe297bd908a36065#hashcode-%E3%81%AE%E5%9F%BA%E6%9C%AC)ためです。

``` java:Sample.java
@EqualsAndHashCode
public class Sample {
  private String name;
  private int age;
}
```

``` java:Sample.class
public class Sample {
  private String name;
  private int age;

  public boolean equals(Object o) {
    if (o == this) return true;
    if (!(o instanceof Person)) return false;
    final Person other = (Person) o;
    if (!other.canEqual((Object) this)) return false;
    final Object this$name = this.name;
    final Object other$name = other.name;
    if (this$name == null ? other$name != null : !this$name.equals(other$name)) return false;
    if (this.age != other.age) return false;
    return true;
  }

  public int hashCode() {
    final int PRIME = 59;
    int result = 1;
    final Object $name = this.name;
    result = result * PRIME + ($name == null ? 0 : $name.hashCode());
    result = result * PRIME + this.age;
    return result;
  }

  protected boolean canEqual(Object other) {
    return other instanceof Person;
  }
}
```

現場では全く使わなかったので、利便性は未知数です。

## Value
`@Value`を付与すると以下のアノテーションが付与され、イミュータブルなオブジェクトとなります。

* `@Getter`
* `@ToString`
* `@EqualsAndHashCode`
* `@AllArgsConstructor`
* クラス及び各フィールドに`final`が付与される
* 各フィールドの可視性が`private`になる

生成時にコンストラクタによって値を設定し、以降は値の変更が不可能になります。
正にイミュータブルなオブジェクトにしたい時に使いたいアノテーションですね。
`staticConstructor`オプションを設定すると、staticなファクトリメソッドを生成できます。
その場合のコンストラクタは`private`に変更されますので、ファクトリメソッドを通さないとインスタンスが生成できなくなります。

## Data
`@Data`付与すると以下のアノテーションが付与された状態と同じになります。

* `@Getter`
* `@Setter`
* `@ToString`
* `@EqualsAndHashCode`
* `@RequiredArgsConstructor`

`@Value`と似たようなアノテーションの機能をまとめたアノテーションです。
こちらは単純なBeanクラスを作るようなイメージに近いです。

# 最後に
いろいろ書いてきましたが、使いこなせないですね。。
`@Value`付けてるのに`final`ってつけていたり。(冗長なだけで普通に動くので問題はありませんが)

今回はよく使用されると思われるアノテーションについて紹介させていただきました。
まだ紹介していないアノテーションもありますし
`staticConstructor`のようなオプションも多く存在しますので、興味のある方はぜひ調べてみてください！！

最後までお読みくださり、ありがとうございました！

## 公式
[Lombok公式](https://projectlombok.org/)

[^1]: ボイラープレートコードとは、言語仕様上省くことができない定型的なコードのこと。ロジックの本質ではないのに書かなければならない冗長コードのこと。
[^2]: 作成後に値が変わることがないオブジェクトのこと。