Lombokメモ

# Lombok とは

- Java で getter / setter やコンストラクタ等のよく使うコードを自動生成してくれるライブラリ
- 例えば、あるクラスに `@Getter` のアノテーションを付与すると、クラス内のフィールドの getter を自動生成してくれる
- 公式ページは[こちら](https://projectlombok.org/)

# 環境

- openjdk 12.0.1
- IntelliJ IDEA CE 2019.1
- lombok 1.18.8

# Lombok を使えるようにする

## IntelliJ での設定

- lombok プラグインをインストールする
  - Preference -> Plugins -> MarketPlace で lombok を検索してインストール
- annotation processing を有効にする
  - Preferences -> Build, Execution, Deployment -> Compiler -> Annotation Processors で Enable annotation processing にチェックを入れる

## build.gradle の設定

`build.gradle` の`dependencies`に以下を追加する

```build.gradle
compileOnly 'org.projectlombok:lombok:1.18.8'
annotationProcessor 'org.projectlombok:lombok:1.18.8'
```

# lombok で生成されたコードの確認

- `delombok`を実行することで、lombok によって生成されたコードを確認できる
- コマンドラインから確認する場合は以下

```shell
java -jar <lombok.jarのパス> delombok -p <アノテーションを付与したクラスのパス>
```

# アノテーション

## `@Getter` / `@Setter`

- 付与したクラスに含まれるフィールドの getter / setter を自動生成する

```java:付与する側
import lombok.Getter;
import lombok.Setter;

import java.util.List;

@Getter
@Setter
public class Human {
    private int age;
    private String name;
    private List<String> hobby;
}
```

```java:生成されたクラス
import java.util.List;

public class Human {
    private int age;
    private String name;
    private List<String> hobby;

    @java.lang.SuppressWarnings("all")
    public int getAge() {
        return this.age;
    }

    @java.lang.SuppressWarnings("all")
    public String getName() {
        return this.name;
    }

    @java.lang.SuppressWarnings("all")
    public List<String> getHobby() {
        return this.hobby;
    }

    @java.lang.SuppressWarnings("all")
    public void setAge(final int age) {
        this.age = age;
    }

    @java.lang.SuppressWarnings("all")
    public void setName(final String name) {
        this.name = name;
    }

    @java.lang.SuppressWarnings("all")
    public void setHobby(final List<String> hobby) {
        this.hobby = hobby;
    }
}
```

## `@ToString`

- `toString()`メソッドを自動生成する

```java:付与する側
import lombok.ToString;

import java.util.List;

@ToString
public class Human {
    private int age;
    private String name;
    private List<String> hobby;
}
```

```java:生成されたクラス
import java.util.List;

public class Human {
    private int age;
    private String name;
    private List<String> hobby;

    @java.lang.Override
    @java.lang.SuppressWarnings("all")
    public java.lang.String toString() {
        return "Human(age=" + this.age + ", name=" + this.name + ", hobby=" + this.hobby + ")";
    }
}
```

## `@NoArgsConstructor` / `@RequiredArgsConstructor` / `@AllArgsConstructor`

- `@NoArgsConstructor` : 引数なしのコンストラクタを自動生成する
- `@RequiredArgsConstructor` : final がついたフィールドを引数にとるコンストラクタを自動生成する
- `@AllArgsConstructor` : 全てのフィールドを引数に持つコンストラクタを自動生成する

```java:付与する側(@AllArgsConstructor)
import lombok.AllArgsConstructor;

import java.util.List;

@AllArgsConstructor
public class Human {
    private int age;
    private final String name;
    private List<String> hobby;
}
```

```java:生成されたクラス
import java.util.List;

public class Human {
    private int age;
    private final String name;
    private List<String> hobby;

    @java.lang.SuppressWarnings("all")
    public Human(final int age, final String name, final List<String> hobby) {
        this.age = age;
        this.name = name;
        this.hobby = hobby;
    }
}
```

## `@Data`

- 以下のアノテーションを付与したのと同じ効果
  - `@Getter` / `@Setter`
  - `@ToString`
  - `@EqualsAndHashCode`
  - `@RequiredArgsConstructor`

## `@Value`

- `@Data`の immutable 版
- 全てのフィールドを private かつ final にする
- setter は生成されない

## `@Builder`

- Builder クラスを自動生成する

```java:付与する側
import lombok.Builder;

import java.util.List;

@Builder
public class Human {
    private int age;
    private final String name;
    private List<String> hobby;
}
```

```java:使用する側
import java.util.Arrays;
import java.util.List;

public class Main {
  public static void main(String[] args) {
    List<String> hobby = Arrays.asList("フットサル", "ダイエット", "読書");
    Human human = new Human.HumanBuilder().age(20).name("名前太郎").hobby(hobby).build();
    System.out.println(human);
  }
}
```

```java:生成されたクラス
import java.util.List;

public class Human {
    private int age;
    private final String name;
    private List<String> hobby;

    @java.lang.SuppressWarnings("all")
    Human(final int age, final String name, final List<String> hobby) {
        this.age = age;
        this.name = name;
        this.hobby = hobby;
    }


    @java.lang.SuppressWarnings("all")
    public static class HumanBuilder {
        @java.lang.SuppressWarnings("all")
        private int age;
        @java.lang.SuppressWarnings("all")
        private String name;
        @java.lang.SuppressWarnings("all")
        private List<String> hobby;

        @java.lang.SuppressWarnings("all")
        HumanBuilder() {
        }

        @java.lang.SuppressWarnings("all")
        public HumanBuilder age(final int age) {
            this.age = age;
            return this;
        }

        @java.lang.SuppressWarnings("all")
        public HumanBuilder name(final String name) {
            this.name = name;
            return this;
        }

        @java.lang.SuppressWarnings("all")
        public HumanBuilder hobby(final List<String> hobby) {
            this.hobby = hobby;
            return this;
        }

        @java.lang.SuppressWarnings("all")
        public Human build() {
            return new Human(age, name, hobby);
        }

        @java.lang.Override
        @java.lang.SuppressWarnings("all")
        public java.lang.String toString() {
            return "Human.HumanBuilder(age=" + this.age + ", name=" + this.name + ", hobby=" + this.hobby + ")";
        }
    }

    @java.lang.SuppressWarnings("all")
    public static HumanBuilder builder() {
        return new HumanBuilder();
    }
}
```

## `@NonNull`

- クラスのフィールドやメソッドの引数に付与すると 自動で null チェックしてくれる

## `@EqualsAndHashCode`

- `equals()`, `hashCode()`メソッドを自動生成する

## `@Log`

- `log`という名前で Logger を自動生成する

```java:@Slf4jを付与した際に生成されるコード
private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(LogExample.class);
```

- `Slf4j` , `Log4j` など様々なライブラリに対応している
- Logger については別途勉強予定

## `var` / `val`

- 変数宣言時に自動で型を推論できる。JDK10 以降では標準実装されたため使わなそう