一、序列化和反序列化的概念
把对象转换为字节序列的过程称为对象的序列化。
把字节序列恢复为对象的过程称为对象的反序列化。
对象的序列化主要有两种用途:
1) 把对象的字节序列永久地保存到硬盘上,通常存放在一个文件中;
2) 在网络上传送对象的字节序列。
在很多应用中,需要对某些对象进行序列化,让它们离开内存空间,入住物理硬盘,以便长期保存。比如最常见的是Web服务器中的Session对象,当有 10万用户并发访问,就有可能出现10万个Session对象,内存可能吃不消,于是Web容器就会把一些seesion先序列化到硬盘中,等要用了,再把保存在硬盘中的对象还原到内存中。
当两个进程在进行远程通信时,彼此可以发送各种类型的数据。无论是何种类型的数据,都会以二进制序列的形式在网络上传送。发送方需要把这个Java对象转换为字节序列,才能在网络上传送;接收方则需要把字节序列再恢复为Java对象。
二、JDK类库中的序列化API
java.io.ObjectOutputStream代表对象输出流,它的writeObject(Object obj)方法可对参数指定的obj对象进行序列化,把得到的字节序列写到一个目标输出流中。
java.io.ObjectInputStream代表对象输入流,它的readObject()方法从一个源输入流中读取字节序列,再把它们反序列化为一个对象,并将其返回。
只有实现了Serializable和Externalizable接口的类的对象才能被序列化。Externalizable接口继承自 Serializable接口,实现Externalizable接口的类完全由自身来控制序列化的行为,而仅实现Serializable接口的类可以 采用默认的序列化方式 。
对象序列化包括如下步骤:
1) 创建一个对象输出流,它可以包装一个其他类型的目标输出流,如文件输出流;
2) 通过对象输出流的writeObject()方法写对象。
对象反序列化的步骤如下:
1) 创建一个对象输入流,它可以包装一个其他类型的源输入流,如文件输入流;
2) 通过对象输入流的readObject()方法读取对象。
三、需求:在网上购物时某用户填写订单,订单内容为产品列表,保存在“save.bin”中;运行时,如果不存在“save.bin”,则进行新订单录入,如果存在,则显示并计算客户所需付款
package com.hlx;
//商品类
public class Product implements java.io.Serializable {
private static final long serialVersionUID = 1L;
private String productNo; // 商品编号
private String name; // 商品名称
private int num; // 数量
public String getProductNo() {
return productNo;
}
public void setProductNo(String productNo) {
this.productNo = productNo;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
public float getPrice() {
return price;
}
public void setPrice(float price) {
this.price = price;
}
private float price; // 价格
/**
* 构造方法
*
* @param productNo
* @param name
* @param num
* @param price
*/
public Product(String productNo, String name, int num, float price) {
this.productNo = productNo;
this.name = name;
this.num = num;
this.price = price;
}
/**
* 输出信息
*/
@Override
public String toString() {
return name + "\t" + price + "\t" + num;
}
}
package com.hlx;
import java.util.*;
//订单类
public class Order implements java.io.Serializable {
private static final long serialVersionUID = 1L;
private String orderNo; // 订单编号
public String getOrderNo() {
return orderNo;
}
public void setOrderNo(String orderNo) {
this.orderNo = orderNo;
}
public ArrayList<Product> getProductList() {
return productList;
}
public void setProductList(ArrayList<Product> productList) {
this.productList = productList;
}
private ArrayList<Product> productList; // 产品列表
public Order(String orderNo) {
this.orderNo = orderNo;
this.productList = new ArrayList<Product>();
}
public Order() {
}
/**
* 计算总价
*
* @return
*/
public double getTotal() {
int total = 0; // 总计的变量
// 循环遍历数据
for (Product pro : productList) {
total += pro.getNum() * pro.getPrice(); // 累计总计
}
return total;
}
}
package com.hlx;
//客户类
public class Customer implements java.io.Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
private String name ; //客户姓名
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Order getOrder() {
return order;
}
public void setOrder(Order order) {
this.order = order;
}
private Order order; //订单
public Customer() { }
}
package com.hlx;
import java.io.File;
import java.io.IOException;
public class TestCutomer {
/**
* 测试类
*
* @param args
* @throws IOException
* @throws ClassNotFoundException
*/
public static void main(String[] args) throws IOException,
ClassNotFoundException {
// 实例化对象
SerializableObj test = new SerializableObj();
// 文件
File file = new File("save.bin");
// 判断文件是否存在?
if (file.exists()) {
test.Load(); // 存在就反序列数据
} else { // 不存在就初始化
test.Init();
test.Save(); // 序列化数据
}
System.out.println("产品名\t单价\t数量");
// 遍历订单的产品
for (Object obj : test.cust.getOrder().getProductList()) {
Product prod = (Product) obj;
// 输出信息
System.out.println(prod);
}
// 显示订单总价
System.out.println("\n订单总价:" + test.cust.getOrder().getTotal());
}
}