【Java】Input,Output,Stream I/O流 04 对象流&序列化

对象流,序列化机制

ObjectInputStream

ObjectOutputStream

序列化 对象 写入转 数据 持久化

反序列化 数据 读取转 对象 活化

 

- 任何实现了Serializable接口的类,其对象可以转化为字节数据,保存和传输时可以还原

- 序列化是RMI [ Remote Method Invoke] 远程方法调用过程的参数和返回值都必须实现的机制

RMI就是JavaEE的基础,所以序列化也是JavaEE的基础

- 实现序列化可以选择两种接口 Serializable Externalizable

 

持久化与活化

如果持久化多个对象或者属性,那么读取时也需要按照同样的顺序读取

public class SerializableTest {
    public static void main(String[] args) throws Exception {
        //persistence();
        activation();
    }
    
    // 对象持久化
    static void persistence() throws Exception {
        // 创建对象流
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream(new File("ObjectStore.txt")));

        // 写入对象
        objectOutputStream.writeObject(new Person("杰哥",24,true,new String[]{"锐普阿伟","狂笑","尾行"}));

        // 刷新
        objectOutputStream.flush();
        // 释放
        objectOutputStream.close();
    }
    // 对象活化
    static void activation() throws Exception {
        ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(new File("ObjectStore.txt")));
        Object object = objectInputStream.readObject();
        if (object instanceof Person) {
            Person person = (Person) object;
            System.out.println(person);
        }
        objectInputStream.close();
    }
}
// 对象要实现可序列化接口
class Person implements Serializable {
    String name;
    Integer age;
    Boolean gender;
    String[] hobby;

    public Person(String name, Integer age, Boolean gender, String[] hobby) {
        this.name = name;
        this.age = age;
        this.gender = gender;
        this.hobby = hobby;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public Boolean getGender() {
        return gender;
    }

    public void setGender(Boolean gender) {
        this.gender = gender;
    }

    public String[] getHobby() {
        return hobby;
    }

    public void setHobby(String[] hobby) {
        this.hobby = hobby;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", gender=" + gender +
                ", hobby=" + Arrays.toString(hobby) +
                '}';
    }
}

 

序列版本UID的意义是?

private static final long serialVersionUID = -6849794470754667710L;

假设在没有这个UID的情况下,序列化的类的对象成功持久化写入文件内

而这个对象的类字段或者其他成员发生了改变,再将对象活化时,这个对象无法被识别是出自这个类的对象

UID就是为了确保对象活化时能够正常的被识别出来,而设置的

 

此外 自定义类中的属性也必须保证是可序列化的(String和基本类型都已经是可序列化的了,要注意是组合自定义类的情况)

序列化无法写入static修饰的和transient修饰的成员变量,值在活化后都为null

 

序列化实现的总结:

- 1 自定义的类和类中的所有属性必须都是实现了序列化接口的!!![注意自定义的属性]

- 2 声明序列版本UID 确保类在变更字段之前持久化的对象,在活化之后能被Java正常识别

- 3 注意static 和 transient 都不能序列化

 

posted @ 2020-04-22 15:36  emdzz  阅读(198)  评论(0编辑  收藏  举报