2、Lombok核心注解详解:@Getter、@Setter、@Data 等基础注解全面解析
学习目标:掌握 Lombok 最常用的 8 个核心注解,理解它们如何简化 POJO 编写,知道每个注解的生成效果、参数配置和适用场景。
1. 为什么需要这些注解?
在 Java 开发中,数据类(POJO/DTO/VO/Entity)通常需要以下方法:
- Getter/Setter:访问和修改字段
- toString():调试和日志输出
- equals() / hashCode():集合操作、去重、缓存键
- 构造器:对象初始化
- 日志对象:记录运行信息
手动编写这些方法不仅繁琐,还容易出错。Lombok 通过注解一键生成,让我们专注业务字段定义。
2. POJO 简化“四件套”
2.1 @Getter 和 @Setter
基本用法
import lombok.Getter;
import lombok.Setter;@Getter
@Setter
public class Product {private Long id;private String name;private Double price;
}
✅ 生成效果:
- 为每个非静态字段生成
public
的 getter 和 setter 方法 - boolean 字段的 getter 以
is
开头(如isActive()
)
// 实际生成的代码(反编译后)
public Long getId() { return this.id; }
public void setId(Long id) { this.id = id; }
public String getName() { return this.name; }
public void setName(String name) { this.name = name; }
// ... 其他字段类似
精细控制
你可以控制访问级别和排除字段:
@Getter(AccessLevel.PROTECTED) // getter 为 protected
@Setter(AccessLevel.NONE) // 禁用所有 setter
public class User {private String username;@Setter(AccessLevel.PRIVATE) // 单独为字段设置private String password;@Getter(AccessLevel.NONE) // 不生成 getterprivate String secretKey;
}
AccessLevel 可选值:
PUBLIC
(默认)、PROTECTED
、PACKAGE
、PRIVATE
、NONE
使用场景
- ✅ 大多数 POJO/DTO/VO/Entity 类
- ❌ 不适用于需要自定义逻辑的 setter(如参数校验)
2.2 @ToString
基本用法
@ToString
public class Order {private Long id;private String customerName;private Double amount;
}
✅ 生成效果:
@Override
public String toString() {return "Order(id=" + this.id + ", customerName=" + this.customerName + ", amount=" + this.amount + ")";
}
常用参数
@ToString(includeFieldNames = true, // 包含字段名(默认 true)callSuper = false, // 是否调用父类 toString()(默认 false)exclude = {"password"}, // 排除敏感字段of = {"id", "name"} // 只包含指定字段(优先级高于 exclude)
)
public class User {private Long id;private String name;private String password; // 不会出现在 toString 中
}
💡 安全提示:永远不要在
toString()
中输出密码、密钥等敏感信息!
使用场景
- ✅ 所有需要日志输出或调试的类
- ✅ API 响应对象(便于排查问题)
2.3 @EqualsAndHashCode
基本用法
@EqualsAndHashCode
public class Book {private String isbn;private String title;
}
✅ 生成效果:
- 基于所有非静态、非 transient 字段生成
equals()
和hashCode()
- 遵循 Java 规范:相等对象必须有相同 hashCode
@Override
public boolean equals(Object o) {if (o == this) return true;if (!(o instanceof Book)) return false;Book other = (Book) o;if (!other.canEqual(this)) return false;final Object this$isbn = this.isbn;final Object other$isbn = other.isbn;if (this$isbn == null ? other$isbn != null : !this$isbn.equals(other$isbn)) return false;// ... 其他字段比较return true;
}@Override
public int hashCode() {final int PRIME = 59;int result = 1;result = result * PRIME + (this.isbn == null ? 43 : this.isbn.hashCode());// ... 其他字段return result;
}
重要参数
@EqualsAndHashCode(callSuper = false, // 是否包含父类字段(默认 false)exclude = {"createTime"}, // 排除字段of = {"id"} // 只基于 id 判断相等性
)
public class Article {private Long id;private String title;private LocalDateTime createTime; // 不参与 equals/hashCode
}
⚠️ 继承警告:如果类有子类,建议设置
callSuper = true
,否则可能违反 equals 对称性。
使用场景
- ✅ 存储在
HashSet
、HashMap
中的对象 - ✅ 需要去重的业务场景
- ❌ 不适用于包含循环引用的对象(可能导致 StackOverflow)
3. 组合注解:事半功倍
3.1 @Data(最常用!)
@Data
是 Lombok 的“瑞士军刀”,组合了多个注解:
// @Data 等价于以下注解的组合:
@Getter
@Setter
@ToString
@EqualsAndHashCode
@RequiredArgsConstructor
使用示例
@Data
public class Student {private Long id;private String name;private Integer age;
}
✅ 自动生成:
- 所有字段的 getter/setter
- toString() 方法
- equals() 和 hashCode()
- @RequiredArgsConstructor:为所有
final
字段和@NonNull
字段生成构造器
注意事项
- 不会生成无参构造器!如果需要,需额外添加
@NoArgsConstructor
- 谨慎用于 JPA Entity:某些框架要求无参构造器
使用场景
- ✅ DTO(数据传输对象)
- ✅ VO(视图对象)
- ✅ 简单的配置类
- ❌ 复杂的业务实体(可能需要自定义 equals/hashCode 逻辑)
3.2 @Value(不可变对象)
@Value
用于创建不可变类(Immutable Class):
@Value
public class Point {private final int x;private final int y;
}
✅ 生成效果:
- 所有字段自动变为
private final
- 只生成 getter(无 setter)
- 生成全参构造器
- 生成 toString、equals、hashCode
等价于:
// 手动编写需要这么多代码!
public final class Point {private final int x;private final int y;public Point(int x, int y) {this.x = x;this.y = y;}public int getX() { return x; }public int getY() { return y; }@Overridepublic boolean equals(Object o) { /* ... */ }@Overridepublic int hashCode() { /* ... */ }@Overridepublic String toString() { /* ... */ }
}
使用场景
- ✅ 配置项(如数据库连接信息)
- ✅ 函数式编程中的值对象
- ✅ 多线程安全的数据载体
4. 构造器注解:灵活初始化
4.1 @NoArgsConstructor
生成无参构造器:
@NoArgsConstructor
public class User {private String name;private Integer age;
}// 生成:public User() {}
重要:JPA、Jackson 等框架通常要求实体类有无参构造器。
4.2 @AllArgsConstructor
生成全参构造器(包含所有字段):
@AllArgsConstructor
public class Product {private Long id;private String name;private Double price;
}// 生成:public Product(Long id, String name, Double price) { ... }
4.3 @RequiredArgsConstructor
生成必需字段构造器:
- 所有
final
字段 - 所有标记
@NonNull
的字段
@RequiredArgsConstructor
public class UserService {private final UserRepository userRepository; // final 字段@NonNullprivate String defaultRole; // @NonNull 字段
}// 生成:public UserService(UserRepository userRepository, String defaultRole) { ... }
💡 Spring 推荐用法:配合
@RequiredArgsConstructor
实现构造器注入,替代@Autowired
。
4.4 构造器组合使用
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Order {private Long id;private String customerName;private Double amount;
}
这样既支持无参构造(框架需要),也支持全参构造(测试或 Builder 模式)。
5. 日志注解:告别手动声明
5.1 @Slf4j(最常用)
自动生成 SLF4J 日志实例:
@Slf4j
public class OrderService {public void processOrder(Order order) {log.info("Processing order: {}", order.getId());log.debug("Order details: {}", order);}
}// 等价于手动编写:
// private static final Logger log = LoggerFactory.getLogger(OrderService.class);
5.2 其他日志框架支持
注解 | 对应框架 |
---|---|
@Log | java.util.logging |
@Log4j | Log4j 1.x |
@Log4j2 | Log4j 2.x |
@CommonsLog | Apache Commons Logging |
@JBossLog | JBoss Logging |
✅ 推荐:使用
@Slf4j
,它是日志门面,便于切换底层实现。
6. 注解使用对比表
注解 | 生成内容 | 典型场景 | 注意事项 |
---|---|---|---|
@Getter/@Setter | getter/setter 方法 | 通用 POJO | 可控制访问级别 |
@ToString | toString() 方法 | 调试、日志 | 排除敏感字段 |
@EqualsAndHashCode | equals()/hashCode() | 集合操作 | 继承时注意 callSuper |
@Data | 以上全部 + RequiredArgsConstructor | DTO、VO | 不生成无参构造器 |
@Value | 不可变类全套方法 | 配置、值对象 | 字段自动 final |
@NoArgsConstructor | 无参构造器 | JPA Entity、Jackson | 框架集成必需 |
@AllArgsConstructor | 全参构造器 | 测试、Builder | 字段顺序敏感 |
@Slf4j | 日志实例 | 所有服务类 | 推荐 SLF4J |
7. 实战示例:完整用户类
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.AllArgsConstructor;
import lombok.ToString;
import lombok.EqualsAndHashCode;
import lombok.extern.slf4j.Slf4j;// 组合使用:DTO 场景
@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString(exclude = "password") // 安全:不打印密码
@EqualsAndHashCode(exclude = "lastLoginTime") // 登录时间不影响用户相等性
@Slf4j
public class UserDTO {private Long id;private String username;private String password; // 敏感字段private String email;private LocalDateTime lastLoginTime;public static void main(String[] args) {UserDTO user = new UserDTO(1L, "john", "secret", "john@example.com", null);log.info("Created user: {}", user); // 不会泄露密码}
}
8. 小结
✅ 你已掌握:
- 四件套注解:
@Getter
/@Setter
/@ToString
/@EqualsAndHashCode
的精细控制 - 组合注解:
@Data
(万能)和@Value
(不可变)的适用场景 - 构造器注解:三种构造器的生成规则和组合使用
- 日志注解:
@Slf4j
快速集成日志
➡️ 下一步:进入 03-Lombok进阶功能实战,学习 @Builder
、@SneakyThrows
等高级功能!
💡 最佳实践提醒:
- 优先使用
@Data
+@NoArgsConstructor
组合- 敏感字段务必在
@ToString
中排除- Entity 类慎用
@Data
,建议手动控制 equals/hashCode 逻辑