实体类必须实现Serializable并显式定义serialVersionUID,字段全用包装类型,提供无参和全参构造器,getter/setter严格遵循JavaBeans规范。

实体类必须实现 Serializable 且显式定义 serialVersionUID
不加 serialVersionUID 看似能编译通过,但一旦类结构变动(比如增减字段、改访问修饰符),反序列化会直接抛 InvalidClassException。JVM 自动生成的 UID 依赖编译器实现和类细节,不可控。
实操建议:
立即学习“Java免费学习笔记(深入)”;
- 用 IDE 自动生成(IntelliJ 快捷键
Alt+Enter→ “Add serialVersionUID”) - 值推荐用
1L或时间戳(如20240501L),避免用随机数——便于版本追踪 - 如果确定永不序列化(如纯 DTO 传给前端),可不加,但需团队明确约定并文档化
字段全部用 private,且禁止使用基本类型(int/boolean 等)
用基本类型会导致 null 值无法表达语义(例如数据库中 is_deleted 为 NULL,boolean deleted 只能是 false),也违反 ORM 框架(如 MyBatis、Hibernate)对可空字段的映射要求。
实操建议:
立即学习“Java免费学习笔记(深入)”;
- 对应数据库
TINYINT(1)或BIT的布尔字段,用Boolean而非boolean - 数值类统一用包装类:
Integer、Long、BigDecimal(金额必用) - 字符串一律用
String,不用char[]或自定义字符容器
构造方法只保留无参 + 全参(或 Builder),禁用带参但漏字段的构造器
漏字段的构造器(比如只传 id 和 name,忽略 createTime)会让对象处于不完整状态,后续被误用时难以排查(尤其在链式调用或 JSON 反序列化后)。
实操建议:
立即学习“Java免费学习笔记(深入)”;
- 必须提供无参构造器——MyBatis/JSON 库依赖它实例化对象
- 全参构造器参数顺序应与字段声明顺序一致,降低阅读成本
- 字段超 4 个时,优先用静态内部
Builder类,避免长参数列表;避免 Lombok 的@AllArgsConstructor自动生成(易失控)
getter/setter 命名严格遵循 JavaBeans 规范,且避免在 setter 中做业务逻辑
像 setUserName(String name) 写成 setUser_name(String name) 或 changeUserName(String name),会导致 Jackson、MyBatis 等框架无法识别属性,静默失败或映射为空。
实操建议:
立即学习“Java免费学习笔记(深入)”;
- 布尔字段 getter 必须是
isXxx()(如isActive()),不能是getXxx();否则 Jackson 默认不识别 - setter 里只做赋值和简单校验(如
Objects.requireNonNull(name)),禁止触发远程调用、DB 查询、发消息等 - 若需计算字段(如
getFullName()),不要加@JsonIgnore就完事,而应在类设计阶段判断:它是真实属性?还是视图层逻辑?后者应移出实体类
public class User implements Serializable {
private static final long serialVersionUID = 20240501L;
private Long id;
private String username;
private String email;
private Boolean isActive;
private BigDecimal balance;
private LocalDateTime createTime;
public User() {}
public User(Long id, String username, String email, Boolean isActive, BigDecimal balance, LocalDateTime createTime) {
this.id = id;
this.username = username;
this.email = email;
this.isActive = isActive;
this.balance = balance;
this.createTime = createTime;
}
// getter/setter 略(按规范生成)
}
字段可空性、序列化行为、ORM 映射规则,这三者稍有错位,运行时就可能表现异常——不是报错,而是数据“悄悄消失”或“默认值覆盖”。写实体类不是堆字段,而是定义契约。










