对象的输入输出流与序列化

import java.io.*;
import java.time.LocalDate;

public class Test {
    public static void main(String[] args){
        SerialCloneTest.test();
    }
}

/*
    2.4 对象输入/输出流与序列化

    2.4.1 保存和加载序列化对象

    保存这样的对象网络是一种挑战,在这里我们当然不能去保存和恢复秘书对象的内存地址,因为当对象
    被重新加载时,它可能占用的是与原来完全不同的内存地址。与此不同的是,每个对象都是用一个序列
    号保存的,这就是这种机制之所以称为对象序列化的原因。下面是其算法:
        1.对你遇到的每一个对象引用都关联一个序列号
        2.对于每个对象,当第一次遇到时,保存其对象数据到输出流中
        3.如果某个对象之前已经被保存过了,那么只写出“与之前保存过的序列好为x的对象相同”。

        ==============================
        =                            =
        =   serial number = 1        =
        =   type = Employee          =
        =   name = "Cat"             =
        =                            =
        ==============================
        =                            =
        =   serial number = 2        =
        =   type = Manager           =
        =   name = "Dog1"            =
        =   secretary = object 1     =
        =                            =
        ==============================
        =                            =
        =   serial number = 2        =
        =   type = Manager           =
        =   name = "Dog2"            =
        =   secretary = object 1     =
        =                            =
        ==============================

    当读回对象时,算法为:
        1.对于对象输入流中的对象,在第一次遇到其序号时,构建它,并使用流中数据来初始化
            它,然后记录这个顺序号和新对象之间的关联。
        2.当遇到“与之前保存过的序列号为x的对象相同”标记时,获取与这个顺序好相关联的对
            象引用。


    2.4.2 理解对象序列化的文件格式
    2.4.5 版本管理
        ——这一部分我没有读,感觉应该会有点意思。

    2.4.4 序列化单例和类型安全的枚举

    在Java的enum类型之前,有一种写法,我觉得这种写法有利于我理解enum:


 */
class Orientation{
    public static final Orientation HORIZONTAL = new Orientation(1);
    public static final Orientation VERTICAL = new Orientation(2);

    private int value;

    private Orientation(int value) {
        this.value=value;
    }
}
/*
    当类型安全的枚举实现Serializable接口时,默认的序列化机制并不可用,你将一个对象写
    进流里,再从流里读出来时,序列化机制会重建新的对象。为了解决这个问题,需要定义另一
    种称为readResolve的特殊序列化方法。如果定义了readResolve方法,在对象序列化之后
    调用它,它必须返回一个对象,而该对象之后会成为readObject的返回值。
 */
class ReadResolveTest{
    //这段代码各种问题,先做一个标记吧
    /*
    protected Object readResolve() throws ObjectStreamException{
        if(value == 1)
            return Orientation.HORIZONTAL;
        if(value == 2)
            return Orientation.VERTICAL;
        throw new ObjectStreamException();
    }
    */
}

/*
    2.4.6 为克隆使用序列化

    思路:
        直接将对象序列化到输出流中,然后将器读回。这样产生的新对象是现有对象
        的一个深拷贝。这个方法尽管灵巧,但是会比显式地构建对象并复制或克隆数
        据域的克隆方法慢多了。
 */
class SerialCloneable implements Cloneable,Serializable{
    public Object clone() throws CloneNotSupportedException {
        try{
            ByteArrayOutputStream bout = new ByteArrayOutputStream();
            try(ObjectOutputStream out = new ObjectOutputStream(bout)){
                out.writeObject(this);
            }

            try(InputStream bin = new ByteArrayInputStream(bout.toByteArray())){
                ObjectInputStream in = new ObjectInputStream(bin);
                return in.readObject();
            }
        } catch (IOException | ClassNotFoundException e) {
            CloneNotSupportedException e2 = new CloneNotSupportedException();
            e2.initCause(e);
            throw e2;
        }
    }
}

class Employee extends SerialCloneable{
    private String name;
    private double salary;
    private LocalDate hireDay;

    public Employee(String name, double salary, LocalDate hireDay) {
        this.name = name;
        this.salary = salary;
        this.hireDay = hireDay;
    }

    public String getName() {
        return name;
    }

    public double getSalary() {
        return salary;
    }

    public LocalDate 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 SerialCloneTest{
    public static void test(){
        Employee harry = new Employee("Harry Hacker",35000,LocalDate.now());

        try {
            Employee harry2 = (Employee)harry.clone();

            harry.raiseSalary(10);

            System.out.println(harry);
            System.out.println(harry2);

        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
    }
}

《Java核心技术卷二》笔记

猜你喜欢

转载自www.cnblogs.com/junjie2019/p/10598503.html
今日推荐