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关键字进行声 ...
随机推荐
- 新 Netflix 开源门户
Netflix 开源改革计划:新 Netflix 开源门户 http://www.oschina.net/news/67555/evolution-of-open-source-at-netflix ...
- JSTL自定义标签库 (二)
要定义自己的标签,首先写个java类,extends TagSupport 或者 implements Tag ,然后在类体里实现自己想要的方法,或者覆盖父类的方法. 我定义的MyTag代码如下: ...
- jquery下php与ajax的数据交换方式
参考链接:http://www.php100.com/html/webkaifa/PHP/PHPyingyong/2013/0122/11971.html 一.前台传递字符串变量,后台返回字符串变量( ...
- Xcode6在10.9.4上面crash解决
具体请看我的evernote 这里: 在10.9.4系统上面直接安装xcode6的beta3.和平时一样, 1.将beta3拖拽到application文件夹中. 2.等待copy完毕,执行xcode ...
- Android之Http通信——3.Android HTTP请求方式:HttpURLConnection
3.Android HTTP请求方式之HttpURLConnection 引言: 好了,前两节我们已经对HTTP协议进行了学习.相信看完前两节的朋友对HTTP协议相比之前 应该更加熟悉吧.好吧.学了要 ...
- iOS UITableView的Section Footer加入button
郝萌主倾心贡献,尊重作者的劳动成果.请勿转载. 假设文章对您有所帮助,欢迎给作者捐赠.支持郝萌主,捐赠数额任意.重在心意^_^ 我要捐赠: 点击捐赠 Cocos2d-X源代码下载:点我传送 在处理UI ...
- asp.net用户身份验证时读不到用户信息的问题 您的登录尝试不成功。请重试。 Login控件
原文:asp.net用户身份验证时读不到用户信息的问题 您的登录尝试不成功.请重试. Login控件 现象1.asp.net使用自定义sql server身份验证数据库,在A机器新增用户A,可以登录成 ...
- python学习之print输出不换行
print的即时打印会导致换行,要使得print的输出不换行,可以在字符串或者变量后面加个逗号(“,”),如下: s = "A bird in the hand..." for c ...
- 黑马day07 注册案例(二)
1依据index.jsp我们首先制定了注册的功能,当点击注册button什么时候.超链接到注册页面.下面是一个注册jsp页 <%@ page language="java" ...
- Codeforces Round#308
A题,看样例就知道要求什么, 水过去 #include <stdio.h> #include <string.h> #include <stdlib.h> #i ...