lombok
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseProject Lombok
Project Lombok
Deep Knowledge: Usewith technology:mcp__documentation__fetch_docsfor comprehensive documentation.lombok
深度知识:使用指定技术为mcp__documentation__fetch_docs即可获取完整官方文档。lombok
Maven Configuration
Maven配置
xml
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.34</version>
<optional>true</optional>
</dependency>
<!-- For MapStruct compatibility -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok-mapstruct-binding</artifactId>
<version>0.2.0</version>
</dependency>xml
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.34</version>
<optional>true</optional>
</dependency>
<!-- 适配MapStruct -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok-mapstruct-binding</artifactId>
<version>0.2.0</version>
</dependency>Common Annotations
常用注解
@Data (All-in-One)
@Data (一站式注解)
java
@Data
public class User {
private Long id;
private String name;
private String email;
}
// Generates:
// - @Getter for all fields
// - @Setter for all non-final fields
// - @ToString
// - @EqualsAndHashCode
// - @RequiredArgsConstructorjava
@Data
public class User {
private Long id;
private String name;
private String email;
}
// 会生成:
// - 所有字段的@Getter
// - 所有非final字段的@Setter
// - @ToString
// - @EqualsAndHashCode
// - @RequiredArgsConstructor@Getter / @Setter
@Getter / @Setter
java
public class User {
@Getter @Setter
private String name;
@Getter // Read-only
private final String email;
@Setter(AccessLevel.PROTECTED)
private String internalId;
}java
public class User {
@Getter @Setter
private String name;
@Getter // 只读
private final String email;
@Setter(AccessLevel.PROTECTED)
private String internalId;
}@NoArgsConstructor / @AllArgsConstructor / @RequiredArgsConstructor
@NoArgsConstructor / @AllArgsConstructor / @RequiredArgsConstructor
java
@NoArgsConstructor
@AllArgsConstructor
public class User {
private Long id;
private String name;
}
@RequiredArgsConstructor
public class UserService {
private final UserRepository userRepository; // Included in constructor
private final UserMapper userMapper; // Included in constructor
private String cacheName; // NOT included
}java
@NoArgsConstructor
@AllArgsConstructor
public class User {
private Long id;
private String name;
}
@RequiredArgsConstructor
public class UserService {
private final UserRepository userRepository; // 包含在构造函数中
private final UserMapper userMapper; // 包含在构造函数中
private String cacheName; // 不包含在构造函数中
}@Builder
@Builder
java
@Data
@Builder
public class User {
private Long id;
private String name;
private String email;
@Builder.Default
private UserStatus status = UserStatus.ACTIVE;
}
// Usage
User user = User.builder()
.name("John")
.email("john@example.com")
.build();
// With toBuilder for updates
User updated = user.toBuilder()
.name("Jane")
.build();java
@Data
@Builder
public class User {
private Long id;
private String name;
private String email;
@Builder.Default
private UserStatus status = UserStatus.ACTIVE;
}
// 使用示例
User user = User.builder()
.name("John")
.email("john@example.com")
.build();
// 结合toBuilder实现更新
User updated = user.toBuilder()
.name("Jane")
.build();@Value (Immutable)
@Value (不可变类注解)
java
@Value
public class UserResponse {
Long id;
String name;
String email;
LocalDateTime createdAt;
}
// Generates:
// - All fields are private final
// - @AllArgsConstructor
// - @Getter (no setters)
// - @ToString
// - @EqualsAndHashCodejava
@Value
public class UserResponse {
Long id;
String name;
String email;
LocalDateTime createdAt;
}
// 会生成:
// - 所有字段为private final
// - @AllArgsConstructor
// - @Getter (无setter)
// - @ToString
// - @EqualsAndHashCodeEntity Pattern
实体模式
java
@Entity
@Table(name = "users")
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@EntityListeners(AuditingEntityListener.class)
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false)
private String name;
@Column(unique = true, nullable = false)
private String email;
@Enumerated(EnumType.STRING)
@Builder.Default
private UserStatus status = UserStatus.ACTIVE;
@CreatedDate
@Column(updatable = false)
private LocalDateTime createdAt;
@LastModifiedDate
private LocalDateTime updatedAt;
// Exclude from toString/equals for performance
@ToString.Exclude
@EqualsAndHashCode.Exclude
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "department_id")
private Department department;
}java
@Entity
@Table(name = "users")
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@EntityListeners(AuditingEntityListener.class)
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false)
private String name;
@Column(unique = true, nullable = false)
private String email;
@Enumerated(EnumType.STRING)
@Builder.Default
private UserStatus status = UserStatus.ACTIVE;
@CreatedDate
@Column(updatable = false)
private LocalDateTime createdAt;
@LastModifiedDate
private LocalDateTime updatedAt;
// 为了性能从toString/equals中排除
@ToString.Exclude
@EqualsAndHashCode.Exclude
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "department_id")
private Department department;
}Service Pattern with Constructor Injection
构造函数注入的服务层模式
java
@Service
@RequiredArgsConstructor
@Slf4j
public class UserServiceImpl implements UserService {
private final UserRepository userRepository;
private final UserMapper userMapper;
private final PasswordEncoder passwordEncoder;
@Override
public UserResponse create(CreateUserRequest dto) {
log.info("Creating user: {}", dto.getEmail());
User user = userMapper.toEntity(dto);
return userMapper.toResponse(userRepository.save(user));
}
}java
@Service
@RequiredArgsConstructor
@Slf4j
public class UserServiceImpl implements UserService {
private final UserRepository userRepository;
private final UserMapper userMapper;
private final PasswordEncoder passwordEncoder;
@Override
public UserResponse create(CreateUserRequest dto) {
log.info("正在创建用户: {}", dto.getEmail());
User user = userMapper.toEntity(dto);
return userMapper.toResponse(userRepository.save(user));
}
}Logging
日志
java
@Slf4j // SLF4J logger
public class UserService {
public void process() {
log.info("Processing...");
log.debug("Debug info: {}", data);
log.error("Error occurred", exception);
}
}
@Log4j2 // Log4j2 logger
@CommonsLog // Apache Commons Logging
@JBossLog // JBoss Loggingjava
@Slf4j // SLF4J日志实例
public class UserService {
public void process() {
log.info("处理中...");
log.debug("调试信息: {}", data);
log.error("发生错误", exception);
}
}
@Log4j2 // Log4j2日志实例
@CommonsLog // Apache Commons Logging日志实例
@JBossLog // JBoss Logging日志实例DTO Pattern
DTO模式
java
// Request DTO
@Data
public class CreateUserRequest {
@NotBlank
private String name;
@Email
private String email;
@Size(min = 8)
private String password;
}
// Response DTO (immutable)
@Value
@Builder
public class UserResponse {
Long id;
String name;
String email;
UserStatus status;
LocalDateTime createdAt;
}java
// 请求DTO
@Data
public class CreateUserRequest {
@NotBlank
private String name;
@Email
private String email;
@Size(min = 8)
private String password;
}
// 响应DTO(不可变)
@Value
@Builder
public class UserResponse {
Long id;
String name;
String email;
UserStatus status;
LocalDateTime createdAt;
}@Cleanup
@Cleanup
java
public void readFile(String path) throws IOException {
@Cleanup InputStream in = new FileInputStream(path);
// in.close() called automatically
}java
public void readFile(String path) throws IOException {
@Cleanup InputStream in = new FileInputStream(path);
// 会自动调用in.close()
}@SneakyThrows
@SneakyThrows
java
@SneakyThrows // Wraps checked exception
public String readConfig() {
return Files.readString(Path.of("config.json"));
}java
@SneakyThrows // 包装受检异常
public String readConfig() {
return Files.readString(Path.of("config.json"));
}@Synchronized
@Synchronized
java
public class Counter {
@Synchronized
public void increment() {
// Thread-safe
}
}java
public class Counter {
@Synchronized
public void increment() {
// 线程安全
}
}@With (Immutable Updates)
@With (不可变对象更新)
java
@Value
@With
public class Point {
int x;
int y;
}
Point p1 = new Point(1, 2);
Point p2 = p1.withX(5); // Point(5, 2)java
@Value
@With
public class Point {
int x;
int y;
}
Point p1 = new Point(1, 2);
Point p2 = p1.withX(5); // Point(5, 2)Key Annotations
核心注解
| Annotation | Purpose |
|---|---|
| Getter, Setter, ToString, Equals, Constructor |
| Immutable class |
| Builder pattern |
| Constructor for final fields |
| Logger field |
| Exclude from toString |
| Exclude from equals/hashCode |
| 注解 | 用途 |
|---|---|
| 生成Getter、Setter、ToString、Equals、构造函数 |
| 生成不可变类 |
| 生成构建器模式代码 |
| 为final字段生成构造函数 |
| 生成日志实例字段 |
| 从ToString方法中排除指定字段 |
| 从Equals/HashCode方法中排除指定字段 |
When NOT to Use This Skill
本技能的不适用场景
| Scenario | Use Instead |
|---|---|
| Java core language | |
| MapStruct mapping | |
| Spring annotations | |
| JPA entities complex logic | Manual implementation |
| Public API design | Explicit methods for clarity |
| 场景 | 请改用 |
|---|---|
| Java核心语言相关问题 | |
| MapStruct映射相关问题 | |
| Spring注解相关问题 | |
| JPA实体复杂逻辑 | 手动实现 |
| 公共API设计 | 显式定义方法保证清晰度 |
Anti-Patterns
反模式
| Anti-Pattern | Why It's Bad | Correct Approach |
|---|---|---|
| @Data on JPA entities | toString/equals issues | Use @Getter/@Setter selectively |
| Not excluding lazy relations | LazyInitializationException | Use @ToString.Exclude |
| @EqualsAndHashCode on entities | Proxy issues | Use @EqualsAndHashCode(onlyExplicitlyIncluded = true) |
| @SneakyThrows everywhere | Hides exceptions | Use proper exception handling |
| @Builder without @Default | Null fields | Add @Builder.Default |
| @Value with mutable fields | Breaks immutability | Use only immutable types |
| Mixing @Data and manual methods | Confusing API | Be consistent |
| Not configuring in lombok.config | Inconsistent behavior | Use lombok.config file |
| 反模式 | 弊端 | 正确做法 |
|---|---|---|
| 给JPA实体加@Data | 会出现toString/equals相关问题 | 按需使用@Getter/@Setter |
| 未排除懒加载关联字段 | 会抛出LazyInitializationException | 使用@ToString.Exclude排除 |
| 给实体类加@EqualsAndHashCode | 会出现代理相关问题 | 使用@EqualsAndHashCode(onlyExplicitlyIncluded = true) |
| 到处使用@SneakyThrows | 会隐藏异常 | 进行合理的异常处理 |
| 使用@Builder但不加@Default | 会出现空字段 | 添加@Builder.Default |
| 给可变字段加@Value | 会破坏不可变性 | 仅配合不可变类型使用 |
| 混用@Data和手动实现方法 | 会导致API混乱 | 保持实现风格一致 |
| 未配置lombok.config | 会出现行为不一致 | 使用lombok.config配置文件 |
Quick Troubleshooting
快速排查
| Issue | Cause | Solution |
|---|---|---|
| "Cannot find symbol" for getters | IDE not processing | Enable annotation processing |
| LazyInitializationException | toString on lazy relation | Add @ToString.Exclude |
| MapStruct not working | Wrong processor order | Lombok before MapStruct |
| Builder missing fields | No @Builder.Default | Add defaults or check config |
| StackOverflowError in equals | Circular reference | Exclude relation fields |
| IDE shows errors but compiles | IDE cache | Invalidate caches/restart |
| @Slf4j logger not found | SLF4J not in classpath | Add SLF4J dependency |
| Generated code not visible | delombok needed | Run delombok task |
| 问题 | 原因 | 解决方案 |
|---|---|---|
| getters相关提示"Cannot find symbol" | IDE未处理注解 | 开启注解处理功能 |
| LazyInitializationException | toString方法调用了懒加载关联字段 | 添加@ToString.Exclude |
| MapStruct不生效 | 注解处理器顺序错误 | 把Lombok处理器放在MapStruct前面 |
| Builder缺失字段 | 未加@Builder.Default | 添加默认值或检查配置 |
| equals方法出现StackOverflowError | 循环引用 | 排除关联字段 |
| IDE显示错误但编译正常 | IDE缓存问题 | 清空缓存/重启IDE |
| 找不到@Slf4j的日志实例 | 类路径缺少SLF4J | 添加SLF4J依赖 |
| 生成的代码不可见 | 需要反编译生成的Lombok代码 | 运行delombok任务 |
Reference Documentation
参考文档
Deep Knowledge: Usewith technology:mcp__documentation__fetch_docsfor comprehensive documentation.lombok
深度知识:使用指定技术为mcp__documentation__fetch_docs即可获取完整官方文档。lombok