序列化Serializable和Externalizable

序列化就是将一个对象(标志对象的类型)及其状态转换为字节码,以文件,内存,数据库等形式保存起来。反序列化就是在适当的时候通过读取这些文件,得到原有状态的对象。
序列化可以通过实现两种接口来实现,即Serializable和Externalizable这两个接口。
Serializable开发相对简单,其读取方式都是但速度慢,而且序列化后的数据文件比较大。

eg1:

package com.lmr.io;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

public class SerialPerson implements Serializable {

    /**
     * 
     */
    private static final long serialVersionUID = -1586881727918562464L;

//  private transient int id;// transient类型,瞬时变量,不会被序列化
    private int id;
    private static int count = 0;
    private String name;
    private int age;
    private String password;

    public SerialPerson(String name, int age, String password) {
        // TODO Auto-generated constructor stub
        id = ++count;
        this.name = name;
        this.age = age;
        this.password = password;
    }

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

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

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    @Override
    public String toString() {
        return "SerialPerson [id=" + id + ", name=" + name + ", age=" + age + ", password=" + password + "]";
    }

    //在序列化前执行,可对要进行序列化的对象进行处理
    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException{
        in.defaultReadObject();
//      password = "456";
    }

    //在反序列化后执行
    private void writeObject(ObjectOutputStream out) throws IOException {
        out.defaultWriteObject();
//      out.writeObject(password);
    }

}
package com.lmr.io;

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

public class TestSerializable {

    public static void main(String[] args) throws IOException {

        String headpath="D:\\TestIOData\\";

        WriteMethod(headpath+"serialperson.txt");

        ReadMethod(headpath+"serialperson.txt");

    }

    public static void WriteMethod(String path) throws IOException{

        FileOutputStream fos=new FileOutputStream(path);
        ObjectOutputStream oos=new ObjectOutputStream(fos);

        for(int i=1;i<10;i++){
            SerialPerson sp=new SerialPerson("A"+i, 10+i,"aBc"+i);
            oos.writeObject(sp);
        }

//      List<SerialPerson> splist=new ArrayList<>();
//      for(int i=1;i<10;i++){
//          SerialPerson sp=new SerialPerson("A"+i, 10+i,"aBc"+i);
//          splist.add(sp);
//      }
//      oos.writeObject(splist);//直接写入对象list,相对应的读取的时候转换的格式也要是list

        oos.close();
        fos.close();

    }

    public static void ReadMethod(String path) throws IOException{

        FileInputStream fis=new FileInputStream(path);
        ObjectInputStream ois=new ObjectInputStream(fis);

        while(true){//使用处理异常的方式来判断文件是否结束

            try {
                SerialPerson sp=(SerialPerson) ois.readObject();//文件读取完毕后,会抛异常
                System.out.println(sp.toString());

            } catch (Exception  e) {
                // TODO Auto-generated catch block
//              e.printStackTrace();
                System.out.println("文件读取完毕!");  
                break;  
            }

        }

//      try {
//          List<SerialPerson> splist=(List<SerialPerson>) ois.readObject();//这里反序列化后的转换格式要跟序列化之前的格式一样
//          
//          for(SerialPerson sp:splist){
//              System.out.println(sp.toString());
//          }
//          
//      } catch (ClassNotFoundException e) {
//          // TODO Auto-generated catch block
//          e.printStackTrace();
//      }

        ois.close();
        fis.close();

    }

}

结果:

SerialPerson [id=1, name=A1, age=11, password=aBc1]
SerialPerson [id=2, name=A2, age=12, password=aBc2]
SerialPerson [id=3, name=A3, age=13, password=aBc3]
SerialPerson [id=4, name=A4, age=14, password=aBc4]
SerialPerson [id=5, name=A5, age=15, password=aBc5]
SerialPerson [id=6, name=A6, age=16, password=aBc6]
SerialPerson [id=7, name=A7, age=17, password=aBc7]
SerialPerson [id=8, name=A8, age=18, password=aBc8]
SerialPerson [id=9, name=A9, age=19, password=aBc9]
文件读取完毕!

若是id的类型改为transient或者为静态变量static,id都将不参与序列化。在反序列化后,id的值为默认值。

SerialPerson [id=0, name=A1, age=11, password=aBc1]
SerialPerson [id=0, name=A2, age=12, password=aBc2]
SerialPerson [id=0, name=A3, age=13, password=aBc3]
SerialPerson [id=0, name=A4, age=14, password=aBc4]
SerialPerson [id=0, name=A5, age=15, password=aBc5]
SerialPerson [id=0, name=A6, age=16, password=aBc6]
SerialPerson [id=0, name=A7, age=17, password=aBc7]
SerialPerson [id=0, name=A8, age=18, password=aBc8]
SerialPerson [id=0, name=A9, age=19, password=aBc9]
文件读取完毕!

Externalizable是继承自Serializable。此接口定义了两个方法,只要实现这两个方法,完成对象的读取。要实现Externalizable接口的类必须有默认构造方法。
相比于Serializable,Externalizable序列化的速度更快,序列化之后的数据更小,但读和取都需要开发人员自行实现。
eg2:

package com.lmr.io;

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

public class ExternalPerson implements Externalizable{

    private int id=0;
    private static int count=0;
    private String name="";
    private int age=0;
    private String password="";

    public ExternalPerson() {//无参构造器,必须有,不然无法进行反序列化
        // TODO Auto-generated constructor stub
//      System.out.println("必须要有无参构造器!!!!");
    }

    public ExternalPerson(String name,int age,String password) {
        // TODO Auto-generated constructor stub
        id=++count;
        this.name=name;
        this.age=age;
        this.password=password;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

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

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String toString() {
        return "ExternalPerson [id=" + id + ", name=" + name + ", age=" + age + ", password=" + password + "]";
    }

    // 在writeExternal之前执行,可以在序列化前对对象进行一些处理,比如加密。
    private Object writeReplace() throws ObjectStreamException {
        this.setPassword(new StringBuffer(password).reverse().toString());//这里对password进行了反转处理
        System.out.println("writeReplace");
        return this;
    }

    @Override
    public void writeExternal(ObjectOutput out) throws IOException {
        // TODO Auto-generated method stub
        out.writeObject(id);
        out.writeObject(name);
        out.writeObject(age);
        out.writeObject(password);
    }

    @Override
    public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
        // TODO Auto-generated method stub
        id=(int) in.readObject();
        name=(String) in.readObject();
        age=(int) in.readObject();
        password=(String) in.readObject();
    }

    // 在readExternal之后执行,可以在反序列化后对得到的对象进行一些处理,比如解密
    private Object readResolve() throws ObjectStreamException {
        //此处可以写对password的解密处理
        System.out.println("readresolve");
        return this;
    }

}
package com.lmr.io;

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

public class TestExternalizable {

    public static void main(String[] args) throws IOException {

        String headpath = "D:\\TestIOData\\";

        EWriteMethod(headpath + "externalperson.txt");

        EReadMethod(headpath + "externalperson.txt");

    }

    public static void EWriteMethod(String path) throws IOException {

        FileOutputStream fos = new FileOutputStream(path);
        ObjectOutputStream oos = new ObjectOutputStream(fos);

        for (int i = 1; i < 10; i++) {
            ExternalPerson ep = new ExternalPerson("A" + i, 10 + i, "ABCD" + i);
            System.out.println(ep.toString());
            oos.writeObject(ep);
//          ep.writeExternal(oos);
        }
        System.out.println("----***************---------");

        oos.close();
        fos.close();

    }

    public static void EReadMethod(String path) throws IOException {

        FileInputStream fis = new FileInputStream(path);
        ObjectInputStream ois = new ObjectInputStream(fis);

        while (true) {// 使用处理异常的方式来判断文件是否结束

            try {
                ExternalPerson ep = (ExternalPerson) (ois.readObject());// 文件读取完毕后,会抛异常
                System.out.println(ep.toString());

            } catch (Exception e) {
                // TODO Auto-generated catch block
                // e.printStackTrace();
                System.out.println("文件读取完毕!");
                break;
            }

        }
        ois.close();
        fis.close();

    }

}

结果:通过使用writeReplace()和readResolve()来对序列化中的对象数据进行处理,writeExternal()可以决定哪些数据参与序列化(跟数据是否被transient修饰没关系),readExternal()则是进行反序列化去解数据。

ExternalPerson [id=1, name=A1, age=11, password=ABCD1]
ExternalPerson [id=2, name=A2, age=12, password=ABCD2]
ExternalPerson [id=3, name=A3, age=13, password=ABCD3]
ExternalPerson [id=4, name=A4, age=14, password=ABCD4]
ExternalPerson [id=5, name=A5, age=15, password=ABCD5]
ExternalPerson [id=6, name=A6, age=16, password=ABCD6]
ExternalPerson [id=7, name=A7, age=17, password=ABCD7]
ExternalPerson [id=8, name=A8, age=18, password=ABCD8]
ExternalPerson [id=9, name=A9, age=19, password=ABCD9]
----***************---------
ExternalPerson [id=1, name=A1, age=11, password=1DCBA]
ExternalPerson [id=2, name=A2, age=12, password=2DCBA]
ExternalPerson [id=3, name=A3, age=13, password=3DCBA]
ExternalPerson [id=4, name=A4, age=14, password=4DCBA]
ExternalPerson [id=5, name=A5, age=15, password=5DCBA]
ExternalPerson [id=6, name=A6, age=16, password=6DCBA]
ExternalPerson [id=7, name=A7, age=17, password=7DCBA]
ExternalPerson [id=8, name=A8, age=18, password=8DCBA]
ExternalPerson [id=9, name=A9, age=19, password=9DCBA]
文件读取完毕!
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值