5
3

More than 1 year has passed since last update.

Lombokのよく使うアノテーション一覧(サンプルコードあります)

Last updated at Posted at 2022-01-28

以前、Java8のStreamAPIに感動した記事を挙げました。そのときStreamAPI以外にも感動したものが、今回記事にしたLombokというライブラリーになります!

最初は何これ?って思っていたのですが、使ってみると使い勝手が良く、かつコードが見やすくなってとても感動しました。

ということもあり、Lombokを知らないプログラマにこの感動を共有したいということでこの記事を書きました。

どうぞ最後までご覧下さい!

この記事でわかること

  • Lombokの概要・仕組み
  • Lombokの導入方法
  • Lombokの基本的なアノテーションと使い方

Lombokとは

アノテーション記述(@xxx)によって、Javaコーディングにおけるボイラープレートコードを排除して、見やすく簡潔に実装することができるライブラリです。

ボイラープレートコードは、省略できない定型的なコードのことを指していて、代表的なところでいうと、以下辺りですかね。

  • getter / setter メソッド
  • equals / hashCodeメソッド
  • toStringメソッド
  • コンストラクタ
  • リソース(入出力ストリーム等)のクローズ処理
  • ロガーインスタンスの生成

Lombokを使用することで、これらのコードを減少させるとともに、可読性や生産性の向上も期待できます!

導入方法

IntelliJ IDEAで導入するサンプルをこちらの記事で書いていますので、ご興味がある方はぜひ参考にしてみてください。

Lombokの仕組み

サンプルコード

Lombokを使わないと以下のようなコードになります。

Lombok未使用
public class People {

  // field
  private Integer year; 
  private String name; 

  // getter
  public Integer getYear() {
    return this.year;
  }

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

  // setter
  public void setYear(final Integer year) {
    this.year = year;
  }

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

fieldごとにsetterとgetterを書かないといけないのが、かなり面倒くさいですよね。

Lombokを使うと以下のようにスッキリとしたコードになります。

Lombok使用
@Getter
@Setter
public class People {

  // field
  private Integer year; // 歳
  private String name;  // 名前

}

@Getter@Setterアノテーションをつけると、Lombokが勝手にgetterメソッドやsetterメソッドを実装してくれます。

これは便利だし、コードの見やすさも爆上がりですね!

どういう仕組みで実現されているか

それじゃあ、サンプルのようにスッキリとしたコードになるのは、どういった仕組みで実現されているのでしょうか。

image.png

コンパイル時のクラスパスにLombokが含まれていると、コンパイル時にLombokがソースファイルを解析して、getterやsetterなどの定型コードを生成したあとにコンパイラに渡します。

ですので、ソースファイルレベルでは定型コードが含まれていなくても、コンパイル後のクラスファイルには定型コードが存在するようになっているんですね~

主に使うLombokアノテーション

開発時によく使うLombokのアノテーションと、どういう効果があるかを表にまとめましたので、ご自分の目的にあったアノテーションを使ってみてください。

アノテーション 説明
@Getter getterメソッドを生成します。
@Setter setterメソッドを生成します。
@ToString toStringメソッドを生成します。
@NonNull Nullチェックのコードを生成します。Nullだった場合NullPointerExceptionがスローされます。
@AllArgsConstructor 全ての引数を使ったコンストラクタを生成します。
@NoArgsConstructor 引数なしのコンストラクタを生成します。
@RequiredArgsConstructor 必須の引数(final)を持つコンストラクタを生成します。
@FieldDefaults(boolean makeFinal, AccessLevel level) アクセス修飾子やfinal修飾子がない変数に対して、アノテーション引数に指定した形で修飾子を付与します。
@EqualsAndHashCode equals、hashCodeメソッドを生成します。
@Data @ToString@Getter@Setter@EqualsAndHashCode@RequiredArgsConstructorの5つのアノテーションをまとめて付与します。
@Value @ToString@Getter@EqualsAndHashCode@AllArgsConstructor
@FieldDefaultsの5つのアノテーションをまとめ付与します。クラスはfinalに、各フィールドはprivate finalになります。
@Builder 対象クラスを生成するためのBuilderクラスを生成します。
@Slf4j slf4jを使ったロギングコードを生成します。その他にもLog4jやCommonsLogなど様々なロガーに対応しています。

各アノテーションのサンプルコード

@Slf4j

これ以降のアノテーションの説明でも@Slf4jを使うケースがあるので先に説明しておきます。

@slf4jを付与することでslf4jを使ったロギングコードを生成します。

@slf4j
@Slf4j
public class DemoSlf4j {
  public static void main(String[] args) {
    log.info("とらのこ");
  }
}

コンパイル時に以下のコードを設定してくれます。

private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(DemoSlf4j.class);
実行結果
> Task :DemoSlf4j.main()
13:57:11.449 [main] INFO training.DemoSlf4j - とらのこ

@Getter@Setter

getterメソッド、setterメソッドを生成します。

@Getter、@Setter
@Slf4j
@Getter
@Setter
public class DemoGetSet {

  private Integer year;
  private String name;

  public static void main(String[] args) {
    DemoGetSet toranoko = new DemoGetSet();
    toranoko.setName("とらのこ");
    log.info(toranoko.getName());
  }
}
実行結果
> Task :DemoGetSet.main()
14:04:39.848 [main] INFO training.DemoGetSet - とらのこ

@ToString

toStringメソッドを生成します。

@ToString
@Slf4j
@Getter
@Setter
@ToString
public class DemoToString {

  private Integer year;
  private String name;

  public static void main(String[] args) {
    DemoToString toranoko = new DemoToString();
    toranoko.setName("とらのこ");
    toranoko.setYear(30);
    log.info(toranoko.toString());
  }
}
実行結果
> Task :DemoToString.main()
14:16:43.438 [main] INFO training.DemoToString - DemoToString(year=30, name=とらのこ)

@ToStringにより、フィールドの状態を文字列で返却してくれます。

@NonNull

Nullチェックのコードを生成します。Nullだった場合NullPointerExceptionがスローされます。

@NonNull
@Slf4j
@Getter
@Setter
public class DemoNonNull {

  private Integer year;

  @NonNull
  private String name;

  public static void main(String[] args) {
    DemoNonNull toranoko = new DemoNonNull();
    toranoko.setYear(30);
    try {
      toranoko.setName(null);
    } catch (NullPointerException e) {
      log.info("ヌルポですよ");
    }
  }
}
実行結果
> Task :DemoNonNull.main()
14:22:18.876 [main] INFO training.DemoNonNull - ヌルポですよ

### @AllArgsConstructor
全ての引数を使ったコンストラクタを生成します。

@AllArgsConstructor
@Slf4j
@Getter
@AllArgsConstructor
public class DemoAllArgsConstructor {

  private Integer year;
  private String name;

  public static void main(String[] args) {
    DemoAllArgsConstructor toranoko = new DemoAllArgsConstructor(30, "とらのこ");
    log.info(toranoko.getName());
  }
}

引数付きのコンストラクタが暗黙的に作成されます!

実行結果
> Task :DemoAllArgsConstructor.main()
14:26:58.664 [main] INFO training.DemoAllArgsConstructor - とらのこ

@NoArgsConstructor@RequiredArgsConstructorについては説明を割愛させていただきます。

@FieldDefaults(boolean makeFinal, AccessLevel level)

image.png

@EqualsAndHashCode

equals、hashCodeメソッドを生成します。

@EqualsAndHashCode
@Slf4j
@AllArgsConstructor
@EqualsAndHashCode
public class DemoEqualsAndHashCode {

  private Integer year;
  private String name;

  public static void main(String[] args) {
    DemoEqualsAndHashCode toranoko1 = new DemoEqualsAndHashCode(30, "とらのこ1");
    DemoEqualsAndHashCode toranoko2 = new DemoEqualsAndHashCode(30, "とらのこ2");
    log.info("ハッシュ値:" + toranoko1.hashCode());
    log.info("比較結果:" + toranoko1.equals(toranoko2));
  }
}
実行結果
> Task :DemoEqualsAndHashCode.main()
14:53:16.322 [main] INFO training.DemoEqualsAndHashCode - ハッシュ値-1058173202
14:53:16.325 [main] INFO training.DemoEqualsAndHashCode - 比較結果false

@Data

@ToString@Getter@Setter@EqualsAndHashCode@RequiredArgsConstructorの5つのアノテーションをまとめて付与します。

@Data
@Slf4j
@Data
public class DemoData {

  private Integer year;
  private final String name;

  public static void main(String[] args) {

    // @RequiredArgsConstructor
    DemoData toranoko1 = new DemoData("とらのこ");
    DemoData toranoko2 = new DemoData("とらのこ");

    // @Setter
    toranoko1.setYear(30);

    // @ToString
    log.info("文字列化:" + toranoko1.toString());

    // @EqualsAndHashCode
    log.info("ハッシュ値:" + toranoko1.hashCode());

    // @Getter,@EqualsAndHashCode
    log.info(
        "比較結果:" + toranoko1.getName().equals(toranoko2.getName()));
  }
}
実行結果
> Task :DemoData.main()
17:36:41.410 [main] INFO training.DemoData - 文字列化DemoData(year=30, name=とらのこ)
17:36:41.417 [main] INFO training.DemoData - ハッシュ値381512457
17:36:41.417 [main] INFO training.DemoData - 比較結果true

@Value

@ToString@Getter@EqualsAndHashCode@AllArgsConstructor@FieldDefaultsの5つのアノテーションをまとめ付与します。

クラスはfinalに、各フィールドはprivate finalになります。(つまり、@Valueに内包される@FieldDefaultsの引数は、makeFinal = true, level = AccessLevel.PRIVATE ということですね)

@Value
@Slf4j
@Value
public class DemoValue {

  Integer year;
  String name;

  public static void main(String[] args) {

    // @AllArgsConstructor
    DemoValue toranoko1 = new DemoValue(30, "とらのこ");
    DemoValue toranoko2 = new DemoValue(30, "とらのこ");

    // @ToString
    log.info("文字列化:" + toranoko1.toString());

    // @EqualsAndHashCode
    log.info("ハッシュ値:" + toranoko1.hashCode());

    // @Getter,@EqualsAndHashCode
    log.info(
        "比較結果:" + toranoko1.getName().equals(toranoko2.getName()));
  }
}
実行結果
> Task :DemoValue.main()
17:43:16.605 [main] INFO training.DemoValue - 文字列化DemoValue(year=30, name=とらのこ)
17:43:16.611 [main] INFO training.DemoValue - ハッシュ値381512457
17:43:16.611 [main] INFO training.DemoValue - 比較結果true

### @Builder
対象クラスを生成するためのBuilderクラスを生成します。

オススメな使い方としては、インスタンスを作りたい対象クラスに@Data@Value@Builderを併用する形です。

@Builder
@Slf4j
@ToString
@Data
@Builder
public class DemoBuilder {

  private Integer year;
  private String name;
  private String gender;

  public static void main(String[] args) {

    // Builerでインスタンス生成
    DemoBuilder toranoko = DemoBuilder.builder()
        .year(30)
        .name("とらのこ")
        .gender("男性")
        .build();

    log.info(toranoko.toString());

  }
}
実行結果
> Task :DemoBuilder.main()
17:51:49.384 [main] INFO training.DemoBuilder - DemoBuilder(year=30, name=とらのこ, gender=男性)

かなり、スッキリとしましたよね。インスタンスを生成するときに、setterを使わなくていいのも当然ながら、どの変数に何を詰めるのかが一見して理解できるというのも利点かなと思います。

さいごに

ここまで、以下を学んできました。

  • Lombokの概要・仕組み
  • Lombokの導入方法(IntelliJ IDEA)
  • Lombokの基本的なアノテーションと使い方
  • @Builder@Data@Valueアノテーションと併用するのがオススメ

ぜひLombokを使って快適なプログラミングライフをお過ごし下さい!

5
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
3