Lombok常用注解

玩家互动 6413

Lombok常用注解

Lombok是一个Java库,通过注解的方式帮助开发者减少样板代码的编写,提高开发效率。本文将Lombok常用注解分类整理,并提供详细说明和使用示例。

目录

构造器相关注解字段相关注解方法相关注解代码简化注解异常处理注解日志相关注解实用工具注解高级用法注解配置与扩展

构造器相关注解

@NoArgsConstructor

作用:生成一个无参构造器。

示例:

@NoArgsConstructor

public class User {

private Long id;

private String name;

}

@AllArgsConstructor

作用:生成一个包含所有字段的构造器。

示例:

@AllArgsConstructor

public class User {

private Long id;

private String name;

}

@RequiredArgsConstructor

作用:为所有带有final修饰或被@NonNull注解的字段生成构造器。

示例:

@RequiredArgsConstructor

public class User {

private final Long id;

@NonNull

private String name;

private Integer age; // 不会包含在生成的构造器中

}

字段相关注解

@Getter

作用:为类的所有字段生成getter方法,也可以单独应用于某个字段。

示例:

@Getter

public class User {

private Long id;

private String name;

}

// 或者单独应用于字段

public class User {

@Getter

private Long id;

private String name;

}

@Setter

作用:为类的所有非final字段生成setter方法,也可以单独应用于某个字段。

示例:

@Setter

public class User {

private Long id;

private String name;

}

// 或者单独应用于字段

public class User {

@Setter

private Long id;

private String name;

}

@NonNull

作用:在生成的方法中添加非空检查,如果参数为null,则抛出NullPointerException。

示例:

public class User {

@NonNull

private String name;

public void setName(@NonNull String name) {

this.name = name;

}

}

@ToString.Exclude

作用:排除特定字段不包含在生成的toString方法中。

示例:

@ToString

public class User {

private Long id;

private String name;

@ToString.Exclude

private String password; // 不会包含在toString方法中

}

方法相关注解

@ToString

作用:生成toString方法,可以通过参数控制包含哪些字段。

示例:

@ToString(exclude = "password")

public class User {

private Long id;

private String name;

private String password;

}

// 或者只包含指定字段

@ToString(of = {"id", "name"})

public class User {

private Long id;

private String name;

private String password;

}

@EqualsAndHashCode

作用:生成equals和hashCode方法。

示例:

@EqualsAndHashCode

public class User {

private Long id;

private String name;

}

// 可以指定使用哪些字段

@EqualsAndHashCode(of = {"id"})

public class User {

private Long id;

private String name;

}

代码简化注解

@Data

作用:组合注解,相当于同时使用了@Getter、@Setter、@ToString、@EqualsAndHashCode和@RequiredArgsConstructor。

示例:

@Data

public class User {

private Long id;

private String name;

}

@Value

作用:创建不可变类,所有字段都被标记为private final,并生成getter方法(没有setter)。

示例:

@Value

public class ImmutableUser {

Long id;

String name;

}

@Builder

作用:实现建造者模式,为类提供一个流式的构建器API。

示例:

@Builder

public class User {

private Long id;

private String name;

private Integer age;

}

// 使用方式

User user = User.builder()

.id(1L)

.name("张三")

.age(25)

.build();

@Accessors

作用:自定义访问器(getter和setter)的行为。

示例:

@Data

@Accessors(chain = true) // 启用链式调用

public class User {

private Long id;

private String name;

}

// 使用方式

User user = new User()

.setId(1L)

.setName("张三");

异常处理注解

@SneakyThrows

作用:允许在不声明throws的情况下抛出受检异常。

示例:

public class FileReader {

@SneakyThrows

public String readFile(String path) {

return Files.readString(Path.of(path)); // 无需显式处理IOException

}

}

日志相关注解

@Slf4j

作用:自动为类添加SLF4J日志对象。

示例:

@Slf4j

public class UserService {

public void saveUser(User user) {

log.info("保存用户: {}", user);

// 业务逻辑

}

}

@Log

作用:自动为类添加java.util.logging.Logger对象。

示例:

@Log

public class UserService {

public void saveUser(User user) {

log.info("保存用户: " + user);

// 业务逻辑

}

}

@Log4j / @Log4j2

作用:自动为类添加Log4j/Log4j2日志对象。

示例:

@Log4j2

public class UserService {

public void saveUser(User user) {

log.info("保存用户: {}", user);

// 业务逻辑

}

}

实用工具注解

@Cleanup

作用:自动管理资源,确保在作用域结束时调用close()方法。

示例:

public void readFile(String path) {

@Cleanup InputStream in = new FileInputStream(path);

// 使用in读取文件

// 方法结束时会自动调用in.close()

}

@Synchronized

作用:方法同步的更安全的变体,使用私有锁对象而不是this。

示例:

public class Counter {

private int count = 0;

@Synchronized

public void increment() {

count++;

}

}

@With

作用:为不可变对象生成"withX"方法,返回字段值被修改的对象副本。

示例:

@Value

@With

public class ImmutableUser {

Long id;

String name;

}

// 使用方式

ImmutableUser user = new ImmutableUser(1L, "张三");

ImmutableUser newUser = user.withName("李四"); // 创建一个新对象,只有name被修改

@Singular

作用:与@Builder一起使用,为集合类型的字段提供单数形式的添加方法。

示例:

@Builder

public class User {

private Long id;

private String name;

@Singular

private List roles;

}

// 使用方式

User user = User.builder()

.id(1L)

.name("张三")

.role("ADMIN") // 单数形式添加

.role("USER") // 可以多次调用

.build();

高级用法注解

@Delegate

作用:实现委托模式,将方法调用委托给指定字段。

示例:

public class UserManager {

@Delegate

private final UserRepository repository = new UserRepositoryImpl();

// 无需实现UserRepository的方法,自动委托给repository字段

}

@FieldDefaults

作用:批量设置字段的访问级别和修饰符。

示例:

@FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true)

public class User {

Long id; // 等同于 private final Long id;

String name; // 等同于 private final String name;

@FieldDefaults(makeFinal = false)

Integer age; // 等同于 private Integer age;

}

@Wither

作用:@With的旧版本,功能相同,为不可变对象生成"withX"方法。

示例:

@Value

@Wither

public class ImmutableUser {

Long id;

String name;

}

@UtilityClass

作用:创建工具类,将构造器设为私有,并将类标记为final。

示例:

@UtilityClass

public class StringUtils {

public String capitalize(String str) {

if (str == null || str.isEmpty()) {

return str;

}

return Character.toUpperCase(str.charAt(0)) + str.substring(1);

}

// 无需手动添加private构造器和final修饰符

}

@Helper

作用:将内部类中的静态方法"提升"到外部类,使其可以直接通过外部类调用。

示例:

public class StringUtils {

@Helper

static class Helpers {

static String capitalize(String str) {

if (str == null || str.isEmpty()) {

return str;

}

return Character.toUpperCase(str.charAt(0)) + str.substring(1);

}

}

// 可以直接通过StringUtils.capitalize()调用

}

@ExtensionMethod

作用:为已有类添加扩展方法,类似于C#的扩展方法。

示例:

@ExtensionMethod({StringExtensions.class})

public class StringProcessor {

public void process(String input) {

// 直接在String对象上调用扩展方法

String result = input.capitalize();

}

}

class StringExtensions {

public static String capitalize(String str) {

if (str == null || str.isEmpty()) {

return str;

}

return Character.toUpperCase(str.charAt(0)) + str.substring(1);

}

}

@SuperBuilder

作用:增强版的@Builder,支持继承关系中的构建器模式。

示例:

@SuperBuilder

public class Person {

private String name;

private int age;

}

@SuperBuilder

public class Employee extends Person {

private String company;

private double salary;

}

// 使用方式

Employee employee = Employee.builder()

.name("张三") // Person类的属性

.age(30) // Person类的属性

.company("ABC公司") // Employee类的属性

.salary(10000.0) // Employee类的属性

.build();

@Jacksonized

作用:与@Builder或@SuperBuilder一起使用,使生成的构建器与Jackson序列化/反序列化兼容。

示例:

@Jacksonized

@Builder

public class User {

private Long id;

private String name;

private int age;

}

// 可以直接通过Jackson反序列化为User对象

@FieldNameConstants

作用:为类的所有字段生成常量名称,便于反射操作和动态查询。

示例:

@FieldNameConstants

public class User {

private String name;

@FieldDefaults(makeFinal = true)

private Long id;

}

// 生成的常量可以这样使用

String idFieldName = User.Fields.id; // "id"

String nameFieldName = User.Fields.name; // "name"

配置与扩展

@Accessors

作用:提供更多自定义选项来控制生成的访问器方法。

参数说明:

chain:启用链式调用,setter方法返回thisfluent:生成不带get/set前缀的访问器prefix:指定要去除的字段前缀

示例:

@Data

@Accessors(fluent = true, chain = true)

public class User {

private Long id;

private String name;

}

// 使用方式

User user = new User()

.id(1L) // 而不是setId

.name("张三"); // 而不是setName

Long userId = user.id(); // 而不是getId

@NonFinal

作用:与@Value一起使用,允许某些字段不是final的。

示例:

@Value

public class ImmutableUser {

Long id;

String name;

@NonFinal

int loginCount; // 不是final,可以修改

}

@PackagePrivate

作用:将字段或方法的访问级别设置为包私有。

示例:

public class User {

@PackagePrivate

String name; // 包私有访问级别

@PackagePrivate

void updateName(String newName) {

this.name = newName;

}

}

lombok.config 配置文件

作用:在项目级别自定义Lombok的行为。

常用配置:

# 停用特定注解

lombok.data.flagUsage=error

lombok.value.flagUsage=error

# 自定义toString方法的格式

lombok.toString.includeFieldNames=false

lombok.toString.doNotUseGetters=true

# 自定义equalsAndHashCode方法

lombok.equalsAndHashCode.callSuper=call

# 自定义访问器

lombok.accessors.chain=true

lombok.accessors.fluent=true

# 自定义日志注解

lombok.log.fieldName=LOGGER

lombok.log.fieldIsStatic=true

@Builder.Default

作用:指定Builder模式中字段的默认值。

示例:

@Builder

public class User {

private Long id;

private String name;

@Builder.Default

private boolean active = true;

@Builder.Default

private List roles = new ArrayList<>(Arrays.asList("USER"));

}

// 使用方式

User user = User.builder()

.id(1L)

.name("张三")

// 不设置active和roles,将使用默认值

.build();

@Tolerate

作用:为自动生成的方法提供替代实现。

示例:

@Data

public class User {

private String name;

@Tolerate

public void setName(String name) {

// 自定义实现,覆盖Lombok生成的setName方法

if (name == null || name.trim().isEmpty()) {

throw new IllegalArgumentException("名称不能为空");

}

this.name = name;

}

}

@Delegate.Exclude

作用:排除某些方法不被@Delegate委托。

示例:

public interface UserRepository {

User findById(Long id);

List findAll();

void save(User user);

void delete(User user);

}

public class UserManager {

@Delegate(excludes = DangerousOperations.class)

private final UserRepository repository = new UserRepositoryImpl();

public interface DangerousOperations {

void delete(User user); // 这个方法不会被委托

}

// 需要自定义实现delete方法

public void delete(User user) {

// 添加额外的安全检查

if (hasPermission()) {

repository.delete(user);

} else {

throw new SecurityException("没有权限删除用户");

}

}

private boolean hasPermission() {

// 权限检查逻辑

return true;

}

}

最佳实践与注意事项

组合使用注解

Lombok注解可以组合使用,但需要注意避免冗余和冲突:

// 推荐的组合

@Value

@Builder

public class ImmutableUser {

Long id;

String name;

}

// 不推荐的组合(冗余)

@Getter

@Setter

@ToString

@EqualsAndHashCode

@NoArgsConstructor // 这些注解可以用@Data替代

public class User {

private Long id;

private String name;

}

与其他框架的集成

Lombok与其他框架集成时的注意事项:

与JPA/Hibernate集成:

@Entity

@Data

@NoArgsConstructor // JPA需要无参构造器

public class User {

@Id

@GeneratedValue(strategy = GenerationType.IDENTITY)

private Long id;

private String name;

@ToString.Exclude // 避免循环引用导致的StackOverflowError

@ManyToMany

private List roles;

}

与Jackson集成:

@Data

@Builder

@NoArgsConstructor // Jackson需要无参构造器

@AllArgsConstructor // 配合@Builder使用

public class User {

private Long id;

private String name;

@JsonIgnore // Jackson注解与Lombok兼容

private String password;

}

与Spring框架集成:

@Service

@RequiredArgsConstructor // 自动注入final字段

@Slf4j

public class UserService {

private final UserRepository userRepository;

public User findById(Long id) {

log.info("查找用户: {}", id);

return userRepository.findById(id)

.orElseThrow(() -> new UserNotFoundException(id));

}

}

调试与反编译

当遇到Lombok相关问题时,可以通过反编译查看生成的代码:

在IDE中使用反编译功能

使用javap -c命令

使用delombok工具:

java -jar lombok.jar delombok src -d delombok-src

其他

Springboot常用注解