Java序列化与反序列化

什么是java序列化和反序列化?
java序列化是指将java中的对象(注意这里只针对对象,对方法无效)通过转化成字节序列存储在文件中,使得其能持久化(持久化就是当JVM停止后,里面的对象还能在下次启动时恢复,其永久存储在了磁盘上)。
反序列化与之相反,将存储在文件中的字节序列恢复成原来的对象。
序列化与反序列化的意义
可以将数据持久化;
能够实现远程通信,在网络上传输数据。
序列化与反序列化方法
1.实现Serializable接口
serializable是一个空的接口,相当于一个标识,实现了它的类表明此类可被序列化。其默认的序列化方法为:使用java.io.ObjectInputStream的writeObject()方法进行序列化;使用java.io.ObjectOutputStream的readObject()方法进行反序列化;测试代码如下

import java.io.Serializable;

public class SerializableTest implements Serializable {

    private static final long serialVersionUID = 1L;

    String name;

    int age;

    String sex;

    public SerializableTest(String name, int age, String sex){
        this.name = name;
        this.age = age;
        this.sex = sex;
    }

    @Override
    public String toString() {
        return "SerializableTest [name=" + name + ", age=" + age + ", sex=" + sex + "]";
    }

}


import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

public class Test {

    public static void main(String[] args) throws IOException, ClassNotFoundException {
        SerializableTest s = new SerializableTest("小明", 12, "男");

        //序列化
        File f = new File("D:/file.out");//创建要输出的文件
        FileOutputStream fo = new FileOutputStream(f);//创建一个文件输出流 
        ObjectOutputStream oo = new ObjectOutputStream(fo);//创建一个对象输出流,接受其他输出流作为参数
        oo.writeObject(s);//通过写对象的方法,将字节序列写入文件中
        oo.close();//关闭对象输出流
        fo.close();//关闭文件输出流

        //反序列化
        FileInputStream fi = new FileInputStream(f);//创建一个文件输入流 
        ObjectInputStream oi = new ObjectInputStream(fi);//创建一个对象输入流,接受其他输入流作为参数
        SerializableTest result = (SerializableTest)oi.readObject();//通过读对象的方法,将字节序列转化为原本对象
        oi.close();//关闭对象输入流
        fi.close();//关闭问价输入流

        System.out.println(result.toString());
    }

}

输出结果为:

SerializableTest [name=小明, age=12, sex=男]

2.实现Externalizable接口
Externalizable接口继承了java.io.Serializable接口,其包含有两个方法:
void writeExternal(ObjectOutput out) throws IOException;
void readExternal(ObjectInput in) throws IOException, ClassNotFoundException;
所以我们可知序列化由writeExternal方法实现,反序列化应该由readExternal实现;下面来看具体的代码:

import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;

public class ExternalizableTest implements Externalizable{
    String name;
    int age;
    String sex;

    public ExternalizableTest() {
        System.out.println("无参构造器");
    }

    public ExternalizableTest(String name, int age, String sex){
        this.name = name;
        this.age = age;
        this.sex = sex;
    }

    @Override
    //序列化,ObjectOutput参数其实就是ObjectOutputStream所实现的一个接口
    public void writeExternal(ObjectOutput out) throws IOException {
        out.writeObject(name);
        out.writeInt(age);
        out.writeObject(sex);
    }

    @Override
    //反序列化,读的顺序应该和写的顺序一致,否则会发生错误
    //ObjectInput参数其实就是ObjectInputStream所实现的一个接口
    public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
        name = (String)in.readObject();
        age = in.readInt();
        sex = (String)in.readObject();
    }

    @Override
    public String toString() {
        return "ExternalizableTest [name=" + name + ", age=" + age + ", sex=" + sex + "]";
    }

}

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

public class Test {

    public static void main(String[] args) throws IOException, ClassNotFoundException {
        ExternalizableTest e = new ExternalizableTest("小红",12,"女");

        //序列化
        File f = new File("D:/file.out");//创建要输出的文件
        FileOutputStream fo = new FileOutputStream(f);//创建一个文件输出流 
        ObjectOutputStream oo = new ObjectOutputStream(fo);//创建一个对象输出流,接受其他输出流作为参数
        e.writeExternal(oo);//一个个的将e对象中的成员变量进行序列化
        oo.close();//关闭对象输出流
        fo.close();//关闭文件输出流

        //反序列化
        FileInputStream fi = new FileInputStream(f);//创建一个文件输入流 
        ObjectInputStream oi = new ObjectInputStream(fi);//创建一个对象输入流,接受其他输入流作为参数
        e.readExternal(oi);//一个个的读出来,在方法中进行赋值
        oi.close();//关闭对象输入流
        fi.close();//关闭问价输入流

        System.out.println(e.toString());

    }

}

结果:

ExternalizableTest [name=小红, age=12, sex=女]

其实从代码来看,两者十分相似,只是Externalizable接口由程序员自己去实现需要序列化的变量,然后调用方法,Serializable接口默认实现对象中所有可序列化的变量。

说到Serializable序列化变量,java中有一个关键字可以使得变量不被默认序列化,那就是transient关键字。被transient所修饰的关键字将不会被默认序列化,但其可以手动进行序列化。

最后说说单例模式如何序列化。
在单例模式情况下,java中使用readResolve()方法来对单例模式进行序列化,在该方法中直接返回单例对象。因为使用普通的序列化方法,在从文件中读取字节流重组对象时,会创建一个对象,这违背了单例模式的规则。
我们重写一个readResolve方法,直接返回该对象实例,在进行反序列化时,JVM对于单例模式将会自动调用此方法来返回一个对象。

//如果该对象被用于序列化,可以保证对象在序列化前后保持一致
    public Object readResolve(){
        return instance;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值