Java IO 对象流与序列化 Java编程思想读书笔记
来源:互联网 发布:高中历史辅助教材淘宝 编辑:程序博客网 时间:2024/06/05 11:27
在Java中,可以通过ObjectOutputStream写出/读取对象。写出对象 :
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("employee.dat")); Employee harry = new Employee("Harry Hacker",50000,1989,10,1); Manager boss = new Manager("Carl Cracker",80000,1987,12,15); out.writeObject(harry); out.writeObject(boss);
读取对象:
ObjectInputStream in = new ObjectInputStream(new FileInputStream("employee.dat")); Employee e1 = (Employee)in.readObject(); Employee e2 = (Employee)in.readObject();
但是,所有在对象流中存储或恢复的类都必须实现Serializable接口(Serializable接口没有任何方法)
class Employee implements Serializable{ ... }
注意:只有在写出对象时才用writeObect/readObject方法,对于基本类型值,需要使用如writeInt/readInt或writeDouble/readDouble这样的方法。(对象流类都实现了DataInput/Dataoutpt接口)
当对象中还有对象属性时,不能简单地保存和恢复对象属性的地址,因为当对象被重新加载时,它可能占据与原来完成不同的内存址。与此不同的是,每个对象都用一个序列号保存,这就是这种机制被称为对象序列化的原因。其具体算法为:
每一个对象引用都关联一个序列号
对于每个对象,当第一次保存时,写出其对象数据到流中
对于某个之前已经被保存过的对象,那么只写出“与之前保存的序列号为x的对象相同”标记
在读回对象时,整个过程反过来:
对于流中的对象,在第一次读取其序列号是地,构建它,并使用流中的数据来初始化它,然后记录这个序列号与构建的对象之间的关联
在读取到“与之前保存过的序列号为x的对象相同”标记,获取与这个序列号相关联的对象引用
可以将不需要序列化的属性域标记为transient,防止它们被序列化。
注意:从不同IO流从同一文件中读取的对象并不相同,在涉及单例时应注意。
序列化版本管理
在程序演化过程中,类的内容也会不断发生变化,序列化读取旧版本的对象时就会引起问题。为了与早期版本保持兼容,可以在类中加入它的版本号:
private static final long serialVersionUID = -8421069283903896412L;
那么这个类的所有较新版本都必须把serialVersionUID常量定义为与最初版本的版本号一致,否则对象流拒绝读入具有不同版本号的对象。
一个类仅有方法发生变化时,在读入新对象数据时才不会有任何问题。但是,如果数据域产生了变化,那么就可能有问题。如,旧文件对象可能比程序中的对象具有更多或更少的数据域,或者数据域的类型可能有所不同。在这些情况下,对象流将尽力将流对象转换为这个类当前的版本。
对象流会将这个类当前版本的数据域与流中版本的数据域进行比较,当然,对象流只会考虑非瞬时和非静态的数据域。如果这两个部分数据域之间名字匹配而类型不匹配,那么对象流不会尝试将一种类型转制成另一种类型,因为这两个对象不兼容;如果流中的对象具有当前版本中所没有的数据域,那么对象流会忽略这些额外的数据,如果当前版本具有在流对象中所没有的数据域,那么这些新添加的域将被设置成它们的默认值(如果是对象则设置为null,如果是数字则为0,如果是boolean值则是false)。
如employee版本1如下 :
public class Employee implements Serializable{ private static final long serialVersionUID = -8421069283903896412L; private String name; public Employee(String n){ this.name = n; } }
Employee em = new Employee("bin"); out = new ObjectOutputStream(new FileOutputStream("employeeWithVersion.dat")); out.writeObject(em);
employee版本升级,添加了数据域salary:
public class Employee implements Serializable{ private static final long serialVersionUID = -8421069283903896412L; private String name; private double salary; public Employee(String n,double s){ this.name = n; this.salary = s; } }
但我们仍然可以使用输入流将开始保存的版本1对象读出,因为我们使用了版本号:
in = new ObjectInputStream(new FileInputStream("employeeWithVersion.dat")); Employee readEm = (Employee) in.readObject();
- Java IO 对象流与序列化 Java编程思想读书笔记
- Java IO 概念 Java编程思想读书笔记
- 38.JAVA编程思想——JAVA IO 对象序列化
- Java IO流与对象IO序列化
- Java IO流与对象IO序列化
- Java IO流与对象IO序列化(转)
- java.io 与对象序列化 笔记
- java语言编程IO流之对象序列化和ObjectInputStream与ObjectOutputStream
- Java编程思想读书笔记(对象)
- Java编程思想读书笔记之对象导论
- 《Java编程思想》读书笔记-第一章/对象导论
- 《Java编程思想》读书笔记1.对象导论
- 《Java编程思想》读书笔记2.一切都是对象
- Java编程思想读书笔记-第一章 对象导论
- java编程思想读书笔记-第一章对象入门
- Java编程思想读书笔记--一切都是对象
- java编程思想读书笔记一:对象导论
- java编程思想读书笔记二:一切都是对象
- 链表的循环带删除操作
- 组合模式
- 实训 mysql ssh
- OOP编程之is-a、has-a和is-like-a之间的关系
- .Net使用程序发送邮件时的问题
- Java IO 对象流与序列化 Java编程思想读书笔记
- CC++初学者编程教程(11) 配置Windows数据库服务器
- Git使用总结
- php 设置字符集为utf-8
- 微信群功能优化升级
- 结构体的简单应用HDU4584
- 关于调试真机时总时出来"想要访问您的钥匙串"提示烦人提示的解决办法
- 设计模式学习——建造者模式(Builder Pattern)/生成器模式
- windows线程创建函数