> 技术文档 > Java实体类 @Data@NoArgsConstructor@AllArgsConstructor@ToString注解_allargsconstructor注解详解

Java实体类 @Data@NoArgsConstructor@AllArgsConstructor@ToString注解_allargsconstructor注解详解

在Java实体类中,@Data@NoArgsConstructor@AllArgsConstructor 和 @ToString 是 Lombok 提供的常用注解

注意事项

  1. Lombok 需要安装插件‌:IDE 中需要安装 Lombok 插件才能正确识别这些注解。
  2. 编译时生成代码‌:这些注解是在编译时通过注解处理器生成代码,而不是运行时。
  3. 不可见但存在‌:生成的代码在源代码中不可见,但编译后的字节码中包含。

一、介绍

1. @Data

  • 作用‌:这是一个组合注解,相当于同时添加了以下注解:
    • @Getter:为所有字段生成 getter 方法
    • @Setter:为所有非 final 字段生成 setter 方法
    • @ToString:生成 toString() 方法
    • @EqualsAndHashCode:生成 equals() 和 hashCode() 方法
    • @RequiredArgsConstructor:为所有 final 字段或标记为 @NonNull 的字段生成构造方法

2. @NoArgsConstructor

  • 作用‌:生成一个无参的构造方法。
  • 适用场景‌:某些框架(如 Hibernate、MyBatis)需要实体类有一个无参构造方法。

3. @AllArgsConstructor

  • 作用‌:生成一个包含所有字段的构造方法(按字段声明顺序)。
  • 注意‌:如果类中有 final 字段且未初始化,使用此注解可能会导致编译错误。

4. @ToString

  • 作用‌:生成 toString() 方法,默认格式为:类名(字段名=字段值, 字段名=字段值...)
  • 常用参数‌:
    • exclude:排除某些字段
    • of:只包含某些字段
    • callSuper:是否包含父类的 toString() 结果
import lombok.*;@Data@NoArgsConstructor@AllArgsConstructor@ToStringpublic class User { private Long id; private String name; private Integer age;}

 对比一下上面的,下面为等效的传统Java代码:

public class User { private Long id; private String name; private Integer age; // @NoArgsConstructor public User() {} // @AllArgsConstructor public User(Long id, String name, Integer age) { this.id = id; this.name = name; this.age = age; } // @ToString @Override public String toString() { return \"User(id=\" + id + \", name=\" + name + \", age=\" + age + \")\"; } // @Data 生成的 getter/setter public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } // @Data 生成的 equals 和 hashCode @Override public boolean equals(Object o) { /* 省略实现 */ } @Override public int hashCode() { /* 省略实现 */ }}

是不是清楚了一些? 

二、为什么要用这些

在Java实体类中设置‌无参构造方法‌、‌有参构造方法‌和‌toString()方法‌,主要是为了满足‌编程规范‌、‌框架兼容性‌和‌开发便利性‌的需求。

1. 为什么要设置无参构造方法(@NoArgsConstructor)?

(1) 框架反射依赖

  • Hibernate、MyBatis、Spring Data JPA‌ 等ORM框架在‌从数据库查询数据并映射到对象‌时,通常需要‌先调用无参构造方法创建对象‌,再通过反射设置字段值。
  • 如果没有无参构造方法,这些框架可能会报错。

(2) 序列化/反序列化需求

  • JSON/XML 反序列化‌(如 JacksonGson)通常需要无参构造方法创建对象,再填充数据。
  • 例如:
    // 反序列化时,Jackson 会先调用无参构造方法,再通过 setter 填充数据User user = objectMapper.readValue(json, User.class);

(3) Java Bean 规范

  • 标准的 Java Bean 要求提供‌无参构造方法‌,以便工具和框架能动态创建实例。

2. 为什么要设置全参构造方法(@AllArgsConstructor)?

(1) 方便对象初始化

  • 在‌手动创建对象‌时,可以直接传入所有参数,避免逐个调用 setter
    // 使用全参构造方法User user = new User(1L, \"张三\", 25);// 对比:没有全参构造方法时,需要逐个 setUser user = new User();user.setId(1L);user.setName(\"张三\");user.setAge(25);

(2) 不可变对象(Immutable Objects)

  • 如果字段是 final 的(不可变),就必须在构造方法中初始化,而不能用 setter
    @AllArgsConstructorpublic class User { private final Long id; // final 字段必须通过构造方法初始化 private final String name;}

(3) 配合 @Builder 使用

  • 如果使用 @Builder(建造者模式),通常需要全参构造方法支持:
    @Builder@AllArgsConstructorpublic class User { private Long id; private String name;}

3. 为什么要重写 toString() 方法(@ToString)?

(1) 调试和日志输出

  • 默认的 Object.toString() 返回的是 类名@哈希码(如 User@1a2b3c),对调试毫无帮助。
  • 重写后,可以直观地看到对象内容:
    User user = new User(1L, \"张三\", 25);System.out.println(user); // 输出:User(id=1, name=张三, age=25)

(2) 日志记录

  • 在日志中打印对象时,toString() 能提供更友好的信息:
    log.info(\"用户信息:{}\", user); // 输出:用户信息:User(id=1, name=张三, age=25)

(3) 避免手动拼接字符串

  • 如果没有 @ToString,每次打印对象都要手动拼接字段:
    // 没有 @ToString 时,需要手动拼接System.out.println(\"User(id=\" + user.getId() + \", name=\" + user.getName() + \")\");

‌做一个小总结‌

注解 作用 适用场景 @NoArgsConstructor 生成无参构造方法 ORM框架(Hibernate/MyBatis)、反序列化(JSON/XML) @AllArgsConstructor 生成全参构造方法 快速初始化对象、不可变对象、Builder模式 @ToString 生成 toString() 调试、日志打印、避免手动拼接字符串 @Data 组合注解(包含@Getter@Setter@ToString@EqualsAndHashCode等) 简化POJO类代码

最佳实践

  • 大多数情况下‌,可以直接用 @Data,它已经包含了 @ToString 和 @RequiredArgsConstructor(部分场景替代 @AllArgsConstructor)。
  • 如果涉及ORM框架‌,额外加上 @NoArgsConstructor
  • 如果需要Builder模式‌,可以加 @AllArgsConstructor 和 @Builder