Demo:
1 public interface Emp extends Serializable{
2 public void work();
3 }
4
5 public class Employee implements Emp{
6 /* 序列化编号 */
7 private static final long serialVersionUID = 1L;
8
9 private String empNo;
10 //透明化处理,不能持久化 瞬时态属性
11 private transient String dept;
12 private String name;
13
14 public Employee(String empNo, String dept, String name) {
15 super();
16 this.empNo = empNo;
17 this.dept = dept;
18 this.name = name;
19 }
20
21 public Employee() {
22 super();
23 }
24
25 public void work() {
26 System.out.println("name:" + this.name + ",empNo:" + this.empNo + ",dept:" + this.dept + " is working.");
27 }
28
29
30 @Override
31 public String toString() {
32 return "Employee [empNo=" + empNo + ", dept=" + dept + ", name=" + name
33 + "]";
34 }
35 }
序列化的过程:
1 public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {
2 String file = "D:emp.dat";
3 Emp e1 = new Employee("001", "技术部", "张三");
4
5 ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(file));
6 out.writeObject(e1);
7 out.close();
8 System.out.println(e1 + "序列化成功");
9
10 ObjectInputStream in = new ObjectInputStream(new FileInputStream(file));
11 Emp e2 = (Emp)in.readObject();;
12 in.close();
13 System.out.println(e2 + "反序列化成功");
14 }
但是看控制台输出的日志信息:
这里就有一个问题,为什么 dept 这个属性没有被序列化呢?
由于 Employee 类中定义的 dept 属性,使用了 transient 关键字修饰,使用了 transient 修饰的属性是不能被序列化的。
解决办法:
这个属性已经存在这个类中,删除这个属性是不可行的,SUN还是提供了一些后门给我们处理这种问题的,就是实现了Serializable接口的类。
如果需要序列化被 transient 修饰的属性,可以通过定义:writeObject(java.io.ObjectOutputStream s)序列化对象和 readObject(java.io.ObjectInputStream s)反序列化对象。这两个方法来实现序列化和反序列化transient的属性。
上面的案例进行修改:
1 public class Employee implements Emp{
2 /* 序列化编号 */
3 private static final long serialVersionUID = 3694902274397865665L;
4
5 private String empNo;
6 //透明化处理,不能持久化
7 private transient String dept;
8 private String name;
9
10 public Employee(String empNo, String dept, String name) {
11 super();
12 this.empNo = empNo;
13 this.dept = dept;
14 this.name = name;
15 }
16
17 public Employee() {
18 super();
19 }
20
21 public void work() {
22 System.out.println("name:" + this.name + ",empNo:" + this.empNo + ",dept:" + this.dept + " is working.");
23 }
24
25
26 @Override
27 public String toString() {
28 return "Employee [empNo=" + empNo + ", dept=" + dept + ", name=" + name
29 + "]";
30 }
31
32 // 强行序列化对象属性的方法
33 private void writeObject(java.io.ObjectOutputStream s)
34 throws java.io.IOException{
35 s.defaultWriteObject();
36 s.writeObject(this.dept);
37 }
38 // 强行反序列化对象属性的方法
39 private void readObject(java.io.ObjectInputStream s)
40 throws java.io.IOException, ClassNotFoundException {
41 s.defaultReadObject();
42 this.dept = (String)s.readObject();
43 }
44 }
这时候就可以把 transient 修饰的属性进行序列化和反序列化了。
总结:
1. 通过实现 Serializable 接口的,默认是不会序列化 transient 修饰的属性,除非重写 writeObject 和 readObject 两个方法。其实这两个方法就是 JVM 在执行 Serializable 接口序列化对象时执行的方法。
2. 如果对象有多个属性都被transient修饰了,例如是empNo和dept,那么在重写writeObject和readObject这两个方法时,一定要注意这两个属性的写入顺序和读取顺序必须保持一致,否则会导致反序列化失败。但是在这里,由于都是字符串格式的,不会报错,只是出现顺序颠倒。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· .NET Core 托管堆内存泄露/CPU异常的常见思路
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
· DeepSeek R1 简明指南:架构、训练、本地部署及硬件要求
· 没有源码,如何修改代码逻辑?
· NetPad:一个.NET开源、跨平台的C#编辑器