
当子类实现serializable而父类未实现时,反序列化会导致父类字段(如泛型id)被初始化为默认值(null),这是java序列化机制对非serializable父类字段的默认处理行为。
当子类实现serializable而父类未实现时,反序列化会导致父类字段(如泛型id)被初始化为默认值(null),这是java序列化机制对非serializable父类字段的默认处理行为。
在Java对象序列化(ObjectOutputStream/ObjectInputStream)过程中,只有显式声明为 Serializable 的类,其所有非瞬态(non-transient)、非静态(non-static)字段才会被序列化和反序列化。若父类未实现 Serializable,即使子类实现了,JVM 在反序列化时不会恢复父类字段的值,而是直接调用父类的无参构造器来初始化该部分状态——而 Entity
本例中,User 实现了 Serializable,但其父类 Entity
- name 和 email(定义在 User 类中,且 User 可序列化)→ 正常还原;
- id(定义在不可序列化的 Entity 父类中)→ 未参与序列化流程,反序列化时由 JVM 调用 Entity 的默认构造逻辑(实际是字段零值初始化),结果为 null。
✅ 正确修复方式:确保整个继承链中所有参与状态保存的类均实现 Serializable:
// 修正:Entity 必须实现 Serializable
public class Entity<ID> implements Serializable {
private static final long serialVersionUID = 1L; // 推荐显式声明
private ID id;
public ID getId() {
return id;
}
public void setId(ID id) {
this.id = id;
}
}
// User 继承已可序列化的 Entity,自身也需实现 Serializable(当前已满足)
public class User extends Entity<Long> implements Serializable {
private static final long serialVersionUID = 2L;
private String name;
private String email;
private List<String> friends;
public User(Long id, String name, String email) {
setId(id); // 此处调用的是 Entity 中的 setId
this.name = name;
this.email = email;
this.friends = new ArrayList<>();
}
// 建议提供无参构造器(非必须,但利于框架兼容性)
public User() {}
}⚠️ 注意事项:
立即学习“Java免费学习笔记(深入)”;
- serialVersionUID 虽非强制,但强烈建议显式声明,避免因编译器自动生成策略差异导致 InvalidClassException;
- 若父类无法修改(如第三方类),可通过在子类中冗余声明同名字段 + 自定义 writeObject/readObject 方法手动序列化父类状态(较复杂,不推荐作为首选);
- 泛型类型(如 ID)在运行时已被擦除,但 Long 实例本身可正常序列化——问题本质不在泛型,而在继承链的序列化可达性。
总结:Java 序列化不是“深拷贝式”自动递归处理所有祖先字段,而是严格以 Serializable 接口为边界。任何需要持久化或网络传输的状态,都必须位于 Serializable 类的直接作用域内。检查并补全继承链上的 Serializable 实现,是解决此类 null 字段问题的根本之道。






