ObjectStreamDemo
当你需要存储相同类型的数据时,使用固定长度的记录格式是一个不错的选择。但,在OOP中创建的对象很少全部都具有相同的类型。
例如,你可能有一个称为staff(见下面demo)的array,它名义上是一个Employee记录数组,但是实际上却包含诸如Manager这样的子类实例。
为解决这个问题,当然可以设计出一种数据格式来存储这种多态集合,但由于有序列化,设计这种类型是没有必要的。
Java语言支持一种称为对象序列化(Object serialization)的非常通用的机制,它可以将任何对象写出到流中,并在之后将其读回。
如果需要对象流中存储或恢复的所有类都进行一下修改,这些类必须实现Serializable接口;
Serializable接口没有任何方法,与Cloneable接口很相似。
只有在写出对象时才能用writeObject/readObject方法,对于基本类型值,需要使用诸如writeInt/readInt或writeDouble/readDouble这样的方法。对象流类都实现了DataInput/DataOutput接口。
由于对象引用而形成的对象网络,Object Serialization不能去保存和恢复对象的地址,因为当对象被重新加载时,JVM为对象分配的内存地址与在另一个JVM中分配的不同。
Object Serialization在处理的办法是使用序列号(serial number):
每个对象都是用一个序列号保存。由于序列化使用序列号代码内存地址,所以允许将对象集合从一台机器传送到另一台机器。正是由于序列号的使用,这种机制被称为对象序列化。
其算法如下:
(1)对遇到的每一个对象引用都关联一个序列号
(2)对于每个对象,当第一次遇到时,保存其对象数据到流中
(3)如果某个对象之前已经被保存过,那么只写出“与之前保存过的序列号为x的对象相同”;在读回对象时,整个过程是反过来的
(4)对于流中的对象,在第一次遇到其序列号时,构建它,并使用流中数据来初始化它,然后记录这个顺序号和新对象之间的关联
(5)当遇到“与之前保存过的序列号为x的对象相同”标记时,获取与这从此顺序号相关联的对象引用
例外的处理:
某些数据域永远都不应该被序列化,例如,只对本地访问有意义的存储文件句柄或窗口句柄的整数值,这种信息在稍后重新加载对象或将其传送到其他机器上时都是没有用处的。事实上,这种域的值如果不恰当,还会引起本地方法崩溃。
Java有一种很简单的机制来防止这种域被序列化,那就是将这些域使用transient关键字来修饰。如果这些域属于不可序列化的类,使用transient关键字修饰即可。瞬时的域在对象被序列化时问题被跳过的。
例如java.awt.geom包中有大量类都是不可能序列化的,例如Point2D.Double,在对象定义使用private transient Point2D.Double point;这样就可以避免NotSerializableException;
在序列化和反序列化对象被认为是惟一时,需要对枚举值做特殊处理。唯一的对象,譬如单例和类型安全的枚举
protected Object readResolve() {
if (value==1) {
return Orientation.HORIZONTAL;
}else if (value==2) {
return Orientation.VERITAL;
}
return null;
}
package io.serial; import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.Date;
import java.util.GregorianCalendar; /*2015-7-9*/
public class ObjectStreamTest {
public static void main(String[] args) {
Employee harry = new Employee("Tom", 20000, 2015, 7, 10);
Manager carl = new Manager("Carl Cracker", 80000, 1987, 12, 15);
carl.setSecretary(harry);
Manager tony = new Manager("Tony Tester", 40000, 1990, 3, 15);
tony.setSecretary(harry); Employee[] staff = new Employee[3];
staff[0] = harry;
staff[1] = carl;
staff[2] = tony; try {
String fileName = "employee.dat";
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(fileName));
out.writeObject(staff);
out.close(); ObjectInputStream in = new ObjectInputStream(new FileInputStream(fileName));
Employee[] newStaff = (Employee[]) in.readObject();
for (Employee employee : newStaff) {
System.out.println(employee);
}
in.close(); } catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} } } class Employee implements Serializable {
private static final long serialVersionUID = -167978670073609475L;
private String name;
private double salary;
private Date hireDay; public Employee(String name, double salary, int year, int month, int dayOfMonth) {
super();
this.name = name;
this.salary = salary;
GregorianCalendar calendar = new GregorianCalendar(year, month - 1, dayOfMonth);
this.hireDay = calendar.getTime();
} public String getName() {
return name;
} public double getSalary() {
return salary;
} public Date getHireDay() {
return hireDay;
} public void raiseSalary(double byPercent) {
double raise = salary * byPercent / 100;
salary += raise;
} @Override
public String toString() {
return getClass().getName() + " [name=" + name + ", salary=" + salary + ", hireDay=" + hireDay + "]";
} } class Manager extends Employee {
private static final long serialVersionUID = -668252664793507835L;
private Employee secretary; public Manager(String name, double salary, int year, int month, int dayOfMonth) {
super(name, salary, year, month, dayOfMonth);
} public void setSecretary(Employee secretary) {
this.secretary = secretary;
} @Override
public String toString() {
return super.toString() + " [secretary=" + secretary + "]";
}
}
Output:
io.serial.Employee [name=Tom, salary=20000.0, hireDay=Fri Jul 10 00:00:00 CST 2015]
io.serial.Manager [name=Carl Cracker, salary=80000.0, hireDay=Tue Dec 15 00:00:00 CST 1987] [secretary=io.serial.Employee [name=Tom, salary=20000.0, hireDay=Fri Jul 10 00:00:00 CST 2015]]
io.serial.Manager [name=Tony Tester, salary=40000.0, hireDay=Thu Mar 15 00:00:00 CST 1990] [secretary=io.serial.Employee [name=Tom, salary=20000.0, hireDay=Fri Jul 10 00:00:00 CST 2015]]
ObjectStreamDemo的更多相关文章
- [源码]ObjectIOStream 对象流 ByteArrayIOStream 数组流 内存流 ZipOutputStream 压缩流
1.对象流 import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File ...
- java-IO
框架图 IO(Input Output)流IO流用来处理设备之间的数据传输,Java对数据的操作是通过流的方式,用于操作流的对象都在IO包中. 流按操作数据分为两种:字节流与字符流 .流按流向分为:输 ...
- [Java面试二]Java基础知识精华部分.
一:java概述(快速浏览): 1991 年Sun公司的James Gosling等人开始开发名称为 Oak 的语言,希望用于控制嵌入在有线电视交换盒.PDA等的微处理器: 1994年将Oak语言更名 ...
- JAVA基础学习day22--IO流四-对象序列化、管道流、RandomAccessFile、DataStream、ByteArrayStream、转换流的字符编码
一.对象序列化 1.1.对象序列化 被操作的对象需要实现Serializable接口 1.2.对象序列化流ObjectOutputStream与ObjectInputStream ObjectInpu ...
- java 21 - 13 IO流之序列化和反序列化
序列化流:把对象按照流一样的方式存入文本文件或者在网络中传输.对象 -- 流数据(ObjectOutputStream) 构造方法:ObjectInputStream(InputStream in) ...
- java对象的序列化与反序列化使用
1.Java序列化与反序列化 Java序列化是指把Java对象转换为字节序列的过程:而Java反序列化是指把字节序列恢复为Java对象的过程. 2.为什么需要序列化与反序列化 我们知道,当两个进程进 ...
- Java 文件IO续
文件IO续 File类 用来将文件和文件夹封装成对象 方便对文件和文件夹的属性信息进行操作 File对象可以作为参数传递给流的构造函数 Demo1 File的构造方法 public cla ...
- javaSE第二十二天
第二十二天 312 1:登录注册IO版本案例(掌握) 312 2:数据操作流(操作基本类型数据的流)(理解) 313 (1)定义: 313 (2)流对象名称 313 (3 ...
- Java IO(四)
对象序列化 对象序列化又叫对象的持久化,对象的串行化(或反串行化) 当使用Serializable接口实现序列化操作时,如果一个对象中的某个属性不希望被序列化,则可以使用transient关键字进行声 ...
随机推荐
- MySQL将表a中查询的数据插入到表b中
MySQL将表a中查询的数据插入到表b中 假设表b存在 insert into b select * from a; 假设表b不存在 create table b as select * from a ...
- hdu 4908 BestCoder Sequence 发现M中值是字符串数, 需要预处理
BestCoder Sequence Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Other ...
- C/S与B/S谁与争锋之我见
看到网上有些人在讨论C/S架构和B/S架构以及它们的发展趋势,后起之秀B/S是否真将取代C/S而存在?在发表我的观点之前,我们先来一起来回顾下C/S以及B/S. 一C/S 1.C/S概念 C/S是Cl ...
- 设计模式六大原则(4):接口隔离原则(Interface Segregation Principle)
接口隔离原则: 使用多个专门的接口比使用单一的总接口要好. 一个类对另外一个类的依赖性应当是建立在最小的接口上的. 一个接口代表一个角色,不应当将不同的角色都交给一个接口.没有关系的接口合并在一起,形 ...
- ecshop 后台添加 成本价 利润
ecshop后台admin中的商品操作php文件,goods.php替换为下面的代码, 还要在数据库商品本店售价后门添加 cost 字段 为 商品成本价 ecs_goods表中添加 cost ...
- VS解决BEX错误但不能关闭DEP保存
报道近期计划BEX错误: 问题签名: 问题事件名称: BEX 应用程序名: Auth.exe 应用程序版本号: 0.0.0.0 应用程序时间戳: 546d9e0c 故障模块名称: Auth.exe 故 ...
- 勾股数组及其应用uva106
勾股数组 设三元组(a,b,c)满足a^2 + b^2 = c^2的勾股数组,那么是否存在无穷多个勾股数组呢, 答案是肯定的,将三元组乘以d,可以得到新的三元组(da,db,dc) 即(da)^2 + ...
- ubuntu12.04 安装和配置jdk1.7
第一步:下载jdk-7-linux-i586.tar.gz wget -c http://download.oracle.com/otn-pub/java/jdk/7/jdk-7-linux-i586 ...
- (七)unity4.6Ugui中国教程文档-------摘要-UGUI Auto Layout
大家好,我是太阳广东. 转载请注明出处:http://write.blog.csdn.net/postedit/38922399 更全的内容请看我的游戏蛮牛地址:http://www.unityman ...
- JS多语种方式
方案: 在不同的移动平台(IOS.Android)上,并建立了HTML页面通信框架.主要业务逻辑HTML发展:我要支持多语言开发. 动机: 通过积极主动的信息方式,前一页完成初始化,获取当前语言选项. ...