Lombok徹底解剖

Javaにおいて、フィールドへのアクセサ等の用意を、アノテーション付与によって肩代わりしてくれる便利なライブラリ、Lombok。

主なアノテーションについてまとめる。

###Getter/Setter

get○○、set○○メソッドを自動で用意してくれる。

```Java:プログラマが書くソース
public class User {
  @Getter
  private userId; 

  @Setter
  private userName; 
}
```

```Java:コンパイルするとこうなる
public class User {
  private userId; 
  private userName; 

  public String getUserId() {
    return this.userId;
  }

  public String setUserName(final String userName) {
    this.userName = userName;
  }
}
```

###EqualsAndHashCode

クラス変数を利用した`equals`,`hashCode`メソッドを追加

```Java:プログラマが書くソース
@EqualsAndHashCode
public class User {

  private String userId;
  private String userName;

}
```

```Java:コンパイルするとこうなる
public class User {

  //デフォルトコンストラクタは省略

　//フィールドの値まで含めて、オブジェクトが一致しているかどうかを判定　
  public boolean equals(final Object o) {
    if (o == this) {
      return true;
    } else if (!(o instanceof User)) {
      return false;
    } else {
　　　//ダウンキャスト　
      User other = (User)o;
      if (!other.canEqual(this)) {
        return false;
      } else {
        Object this$userId = this.userId;
        Object other$userId = other.userId;
        if (this$userId == null) {
          if (other$userId != null) {
            return false;
          }
        } else if (!this$userId.equals(other$userId)) {
          return false;
        }

        Object this$userName = this.userName;
        Object other$userName = other.userName;
        if (this$userName == null) {
          if (other$userName != null) {
            return false;
          }
        } else if (!this$userName.equals(other$userName)) {
          return false;
        }

        return true;
      }
    }
  }

  protected boolean canEqual(final Object other) {
    return other instanceof User;
  }

  public int hashCode() {
    int PRIME = true;
    int result = 1;
    Object $userId = this.userId;
    int result = result * 59 + ($userId == null ? 43 : $userId.hashCode());
    Object $userName = this.userName;
    result = result * 59 + ($userName == null ? 43 : $userName.hashCode());
    return result;
  }
}
```

###ToString

そのまま。クラス及びメンバの情報を文字列として出力。

```Java:プログラマが書くソース
@ToString
public class User {

  private String userId;
  private String userName;

}
```

```Java:コンパイルするとこうなる
public class User {
  private userId; 
  private userName; 

  public String toString() {
    return "User(userId=" + this.userId + ", userName=" + this.userName + ")";
  }
}
```

###AllArgsConstructor
メンバすべてを引数とするコンストラクタを生成。

```Java:プログラマが書くソース
@AllArgsConstructor
public class User {

  private String userId;
  private String userName;

}
```

```Java:コンパイルするとこうなる
public class User {
  private userId; 
  private userName; 

  public User(final String userId, final String userName) {
    this.userId = userId;
    this.userName = userName;
  }
}
```

なお、内部クラスを持たせると、その内部クラスはコンストラクタに含まれない。
内部クラスそのものに別途AllArgsConstructorを付与の上、インスタンスをセットする必要がある。

```Java:プログラマが書くソース（内部クラスあり）
@AllArgsConstructor
public class User {

  private String userId;
  private String userName;

  private class UserSub {

    private String subUserId;
    private String subUserName;
  }
}
```

```Java:コンパイルするとこうなる（内部クラスあり）
//内部クラスはコンストラクタ変数にはならない

public class User {
  private String userId;
  private String userName;

  public User(final String userId, final String userName) {
    this.userId = userId;
    this.userName = userName;
  }

  private class UserSub {
    private String subUserId;
    private String subUserName;

    private UserSub() {
    }
  }
}
```

###NoArgsConstructor
引数を持たないコンストラクタを生成。
Javaのクラスはコンストラクタを明示的に書かない場合、lombok無しでも引数なしコンストラクタを生成するので、これっていつ必要なのかな...

```Java:プログラマが書くソース
@NoArgsConstructor
public class User {

  private String userId;
  private String userName;

}
```

```Java:コンパイルするとこうなる
public class User {
  private userId; 
  private userName; 

  public User() {
  }
}
```

###RequiredArgsConstructor
コンストラクタでの初期化必須(="final")なメンバを引数としたコンストラクタを生成。

```Java:プログラマが書くソース
@RequiredArgsConstructor
public class User {

  private String userId;
  private String userName;

}
```

```Java:コンパイルするとこうなる
public class User {
  private final String userId;
  private String userName;

  public User(final String userId) {
    this.userId = userId;
  }
}
```

###Data
getter,setter,equals,hashCode,toStringをまとめて実装してくれる。

```Java:プログラマが書くソース
@Data
public class User {

  private String userId;
  private String userName;

}
```

```Java:コンパイルするとこうなる
public class User {
  private String userId;
  private String userName;

  public User() {
  }

  public String getUserId() {
    return this.userId;
  }

  public String getUserName() {
    return this.userName;
  }

  public void setUserId(final String userId) {
    this.userId = userId;
  }

  public void setUserName(final String userName) {
    this.userName = userName;
  }

  public boolean equals(final Object o) {
    if (o == this) {
      return true;
    } else if (!(o instanceof User)) {
      return false;
    } else {
      User other = (User)o;
      if (!other.canEqual(this)) {
        return false;
      } else {
        Object this$userId = this.getUserId();
        Object other$userId = other.getUserId();
        if (this$userId == null) {
          if (other$userId != null) {
            return false;
          }
        } else if (!this$userId.equals(other$userId)) {
          return false;
        }

        Object this$userName = this.getUserName();
        Object other$userName = other.getUserName();
        if (this$userName == null) {
          if (other$userName != null) {
            return false;
          }
        } else if (!this$userName.equals(other$userName)) {
          return false;
        }

        return true;
      }
    }
  }

  protected boolean canEqual(final Object other) {
    return other instanceof User;
  }

  public int hashCode() {
    int PRIME = true;
    int result = 1;
    Object $userId = this.getUserId();
    int result = result * 59 + ($userId == null ? 43 : $userId.hashCode());
    Object $userName = this.getUserName();
    result = result * 59 + ($userName == null ? 43 : $userName.hashCode());
    return result;
  }

  public String toString() {
    return "User(userId=" + this.getUserId() + ", userName=" + this.getUserName() + ")";
  }
}
```