package serializ;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
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;
/**
* 类要实现序列化,必须实现Serializable接口 <br>
* 但该接口并没有任何方法要实现 <br>
* 一般序列化可以保存到字节数据或者文件 <br>
* 比如为了实现对象在系统间传输
*
* @author yli
*
*/
public class Employee implements Serializable {
/**
* 一旦实现Serializable接口,就应该定义默认的序列ID
* 因为类可以不断升级,比如增加字段或者增加方法
* 那么老版本的类和新版本的类,如果通过序列化关联起来
* 就要求新老版本的类拥有相同的 serialVersionUID
*
* @see 在JDK的bin目录,有serialver.exe程序,可以用于生成每个类的UID
*/
private static final long serialVersionUID = 5128673904770381297L;
protected String name;
protected double salary;
public Employee(String name, double salary) {
this.name = name;
this.salary = salary;
}
public String toString() {
return String.format("{name:%s,salary:%s}", this.name, this.salary);
}
public Employee getEmp() {
return this;
}
public static void main(String[] args) {
String file = "src/serialize.dat";
Employee emp1 = new Employee("yli", 10000d);
System.out.println("==>write Employee");
System.out.println(emp1);
writeObject(emp1, file);
System.out.println("==>read Employee");
Employee emp2 = (Employee) readObject(file);
System.out.println(emp2);
System.out.println("============================");
System.out.println(String.format("(emp1==emp2)===>%s", emp1 == emp2));
// 反序列化之后两个对象不会相等
// 因为反序列化回来内存地址肯定不一样,比如在另一台机器上反序列化
// 地址是不可能相等的,那如果A对象被B、C对象引用
// A、B、C 全部序列化了,那反序列化回来之后:B、C持有的A对象还是相等的吗?
// Java的序列化机制保证了反序列化回来之后持有的A对象想的
Manager m1 = new Manager("m1", 15000d);
m1.setEmp(emp1);
Manager m2 = new Manager("m2", 20000d);
m2.setEmp(emp1);
Employee[] emps1 = new Employee[]{emp1,m1,m2};
System.out.println("==>write Employee[]");
writeObject(emps1, file);
System.out.println("==>read Employee[]");
Employee[] emps2 = (Employee[]) readObject(file);
// 打印结果显示m1和m2持有的emp对象是相同的
// 因为在序列化每个对象时,会为这对象产生唯一的序列号Id
// 比如emp1序列化成功后,产生序列Id:001
// 那么m1和m2在序列化时,因为关联到同一个employee对象
// 且发现emp1对象已经序列化了,则m1和m2都关联到 emp1的Id:001 上面即可
// 反序列化过程也要依赖每个对象的Id
System.out.println(String.format("(emps2[0]==emps2[1].getEmp()===>%s)", emps2[0]==emps2[1].getEmp()));
System.out.println(String.format("(emps2[0]==emps2[2].getEmp()===>%s)", emps2[0]==emps2[2].getEmp()));
}
// 序列化对象
private static void writeObject(Object obj, String file) {
ObjectOutputStream oos = null;
try {
oos = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(file)));
oos.writeObject(obj);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
oos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
// 反序列化
private static Object readObject(String file) {
ObjectInputStream ois = null;
Object obj = null;
try {
ois = new ObjectInputStream(new BufferedInputStream(new FileInputStream(file)));
obj = ois.readObject();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally {
try {
ois.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return obj;
}
}
class Manager extends Employee {
private static final long serialVersionUID = -3030759793812915423L;
private Employee emp;
public Manager(String name, double salary) {
super(name, salary);
}
public Employee getEmp() {
return emp;
}
public void setEmp(Employee emp) {
this.emp = emp;
}
public static long getSerialversionuid() {
return serialVersionUID;
}
}