71 Serializable(序列化和反序列化)

对象的输出流:ObjectOutputStream  把对象输出到文件存储起来,我们称作为序列化
对象的输入流:ObjectInputStream   把对象从文件中读取出来,我们称作为反序列化

ObjectOutputStream
    构造方法:
        ObjectOutputStream()
            为完全重新实现 ObjectOutputStream 的子类提供一种方法,让它不必分配仅由 ObjectOutputStream 的实现使用的私有数据。
        ObjectOutputStream(OutputStream out)
            创建写入指定 OutputStream 的 ObjectOutputStream。
    一些方法:
        writeObject(Object obj)   将指定的对象写入 ObjectOutputStream。
    注意:其他的一些方法可以查看jdk文档

ObjectInputStream
    构造方法:
        ObjectInputStream()
            为完全重新实现 ObjectInputStream 的子类提供一种方式,让它不必分配仅由 ObjectInputStream 的实现使用的私有数据。
        ObjectInputStream(InputStream in)
            创建从指定 InputStream 读取的 ObjectInputStream。
    一些方法:
        readObject()    从 ObjectInputStream 读取对象。
            注意:readObject方法一次只会读取一个对象,如果想要读取多个对象需要利用EOFException
            EOFException  此异常主要被数据输入流用来表明到达流的末尾。
            其他许多输入操作返回一个特殊值表示到达流的末尾,而不是抛出异常。

        注意:其他的一些方法可以查看jdk文档
        
对象的输入输出流作用:对象的输入输出流主要的作用是用于读写对象的信息。对象一但写到文件上那么就可以做到持久化了

对象的输入输出流的使用步骤:
    1.被序列化对象的所属类必须实现Serializable(标识)接口
    2.给被序列化对象的所属类指定SerialVersionUID值(可选)
    3.被序列化对象的所属类的某些隐秘成员要使用transient修饰(可选)

对象输入输出流要注意的细节:
    1.如果对象需要被写出到文件上,那么对象所属的类必须要实现Serializable接口。Serializable只是一个没有任何方法的接口,一般这样的接口我们称作为标识接口
    2.对象的反序列化创建对象的时候并不会调用构造方法
    3.SerialVersionUID适用于记录被写入对象所属类的版本信息的    ,ServialVersionUID这个数字是通过一个类名、成员、包名、工程名算出来的一个数字
    4.如果反序列化的时候,ServialVersionUID不一致,那么会反序列化失败,也就是接受ObjectOutputStream的writeObject方法的返回值的所属类的版本信息一定要跟存入文本时的对象所属类的版本信息一样(类名、成员、包名、工程名一样)
    5.如果序列化和反序列化的时候可能会修改类的成员,那么最好一开始就给这个类指定一个ServialVersionUID,那么当我们把对象存入文本中的时候jvm不会自己再算ServialVersionUID。这个就可以保证接受对象和存入对象的所属类的版本信息一样,我们也就可以修改成员了(我自己偏向于指定,毕竟有时候自己并不知道会不会修改)
    6.如果一个对象某些数据不想被序列化到硬盘上,那么对象的所属类的成员变量可以使用transient(中文:透明)修饰,这样就可以保证被修饰的数据就不会序列化到硬盘上,当然反序列的时候也得不到这个数据
    7.如果要被序列化对象所属类的内部维护了另一个类的引用,那么另一个类也需要实现Serializable接口,当然版本信息也需要相同

下面是一些实例:

class Work implements Serializable{

    private static final long serialVersionUID = 1L;
    String workname;
    double money;

    public Work(String workname , double money) {
        this.workname = workname;
        this.money = money;
    }
}

class People implements Serializable{
    //指定版本编号
    private static final long serialVersionUID = 1L;
    transient int card;    //身份证涉及隐私我们可以使用transient修饰,不序列化到硬盘中
    String name;
    int age;

    //维护一个另一个类的引用
    Work work;

    public People(int card ,String name , int age,Work work) {
        this.card = card;
        this.name = name;
        this.age = age;
        this.work = work;
    }

    //自定义输出格式
    @Override
    public String toString() {

        return "{省份证编号:"+this.card+"  姓名:"+this.name+" 年龄:"+this.age+" 工作:"+work.workname+" 工资:"+this.work.money+"}";
    }
}

public class Demo1 {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        writeObject();
        readObject();
    }
    //序列化,把对象存入硬盘中
    public static void writeObject() throws IOException {
        //找到目标文件
        File file = new File("D:\\新建文件夹\\a.txt");
        //建立数据传输通道
        FileOutputStream fileOutputStream = new FileOutputStream(file);
        //建立对象的传输通道
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
        //序列化对象,写入硬盘
        objectOutputStream.writeObject(new People(1001,"张三",18,new Work("打酱油",5000.0)));
        objectOutputStream.writeObject(new People(1002,"李四",19,new Work("收酱油",5000.0)));
        //关闭资源
        objectOutputStream.close();//相当于fileOutputStream.close()
    }

    //反序列化
    public static void readObject() throws IOException{
        //找到目标文件
        File file = new File("D:\\新建文件夹\\a.txt");
        //建立数据传输通道
        FileInputStream fileInputStream = new FileInputStream(file);
        //建立对象的传输通道
        ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);
        //读取文件
        //EOFException  此异常主要被数据输入流用来表明到达流的末尾。
        //注意,其他许多输入操作返回一个特殊值表示到达流的末尾,而不是抛出异常。
        People p;
        while(true) {
            try {
                p = (People)objectInputStream.readObject();
                System.out.println(p);
            } catch(EOFException e) {
                break;
            }catch(ClassNotFoundException e) {
                break;
            }
        }
        objectInputStream.close();//相当于fileInputStream.close()
    }
}

文件被序列化到文本中存储的内容

文件被反序列化

从这里我们可以发现,我们使用transient修饰的card没有被写入和读取出来(0是默认的初始值)

原文地址:https://www.cnblogs.com/zjdbk/p/9090264.html

时间: 2024-07-30 16:18:24

71 Serializable(序列化和反序列化)的相关文章

Serializable 序列化和反序列化

遇到这个 Java Serializable 序列化这个接口,我们可能会有如下的问题:a)什么叫序列化和反序列化b)作用.为啥要实现这个 Serializable 接口,也就是为啥要序列化c)serialVersionUID 这个的值到底是在怎么设置的,有什么用.有的是1L,有的是一长串数字,迷惑ing.      我刚刚见到这个关键字 Serializable 的时候,就有如上的这么些问题. 在处理这个问题之前,你要先知道一个问题,这个比较重要.这个Serializable接口,以及相关的东西

Java 之 Serializable 序列化和反序列化的概念,作用的通俗易懂的解释

遇到这个 Java Serializable 序列化这个接口,我们可能会有如下的问题a,什么叫序列化和反序列化b,作用.为啥要实现这个 Serializable 接口,也就是为啥要序列化c,serialVersionUID 这个的值到底是在怎么设置的,有什么用.有的是1L,有的是一长串数字,迷惑ing.我刚刚见到这个关键字 Serializable 的时候,就有如上的这么些问题. 在处理这个问题之前,你要先知道一个问题,这个比较重要.这个Serializable接口,以及相关的东西,全部都在 J

[转]Java 之 Serializable 序列化和反序列化的概念,作用的通俗易懂的解释

原文地址:https://blog.csdn.net/qq_27093465/article/details/78544505 遇到这个 Java Serializable 序列化这个接口,我们可能会有如下的问题: 1.什么叫序列化和反序列化 2.作用.为啥要实现这个 Serializable 接口,也就是为啥要序列化 3.serialVersionUID 这个的值到底是在怎么设置的,有什么用.有的是1L,有的是一长串数字,迷惑ing. 我刚刚见到这个关键字 Serializable 的时候,就

单例模式序列化与反序列化

package com.wz.thread.resolve; import java.io.ObjectStreamException;import java.io.Serializable;/** * 序列化与反序列化 * @author Administrator * */public class MyObject implements Serializable {    private static final long serialVersionUID = 607305371105699

java的序列化和反序列化

package com.lideng.work325; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOExceptio

序列化与反序列化总结(Serializable和Parcelable)

序列化是指将对象的状态信息转换为可以存储或传输的形式的过程. 在Java中创建的对象,只要没有被回收就可以被复用,但是,创建的这些对象都是存在于JVM的堆内存中,JVM处于运行状态时候,这些对象可以复用, 但是一旦JVM停止,这些对象的状态也就丢失了. 在实际生活中,需要将对象持久化,需要的时候再重新读取出来,通过对象序列化,可以将对象的状态保存为字节数组,需要的时候再将字节数组反序列化为对象. 对象序列化可以很容易的在JVM中的活动对象和字节数组(流)之间转换,广泛用于RMI(远程方法调用)以

Java对象的序列化和反序列化Serializable

1.什么是序列化和反序列化 Serialization(序列化)是一种将对象以一连串的字节描述的过程:反序列化deserialization是一种将这些字节重建成一个对象的过程. 2.什么情况下需要序列化 a)当你想把的内存中的对象保存到一个文件中或者数据库中时候: b)当你想用套接字在网络上传送对象的时候: c)当你想通过RMI传输对象的时候: 3.如何实现序列化 将需要序列化的类实现Serializable接口就可以了,Serializable接口中没有任何方法,可以理解为一个标记,即表明这

Java基础:序列化(Serializable)与反序列化

在学习IO中的ObjectOutputStream和ObjectInputStream时,会涉及到序列化和反序列化的应用,那么它们是什么? 一.概念 序列化:把对象转换为字节序列的过程,叫做对象的序列化. 反序列化:把字节序列恢复为对象的过程,叫做对象的反序列化. 二.作用 主要有两种用途: 1.把对象的字节序列永久保存在硬盘中,也就是把内存中的数据(对象)持久化处理. 2.可以在网络上传输对象的字符序列,对象不再局限于本地使用. 无论那种用途,实际上都是为了保存在内存中的各种对象的状态(也就是

Serializable的序列化与反序列化

使用Serializable序列化,只要实现Serializable接口即可.一般情况下都会显示设置静态成员变量serialVersionUID为固定值.序列化时使用ObjectOutputStream写入,反序列化时使用ObjectInputStream读出. 如此简单,谁都会.但这是我碰到复杂点的情况,特作以下总结: 1.Serializable可继承:父类实现了序列化,子类也会自动实现序列化 PersonBean.java: public class PersonBean implemen