JAVA序列化和反序列化

序列化首先解释两个概念:什么是序列化,什么又是反序列化

序列化:将对象转化成留的过程称为序列化。

反序列化:将流转化成对象的过程称之为反序列化。


Java 序列化技术可以使你将一个对象的状态写入一个Byte 流里,并且可以从其它地方把该Byte 流里的数据读出来,重新构造一个相同的对象。这种机制允许你将对象通过网络进行传播,并可以随时把对象持久化到数据库、文件等系统里。Java的序列化机制是RMI、EJB等技术的技术基础。


序列化的用途:

1.利用对象的序列化实现保存应用程序的当前工作状态,下次再启动的时候将自动地恢复到上次执行的状态。

2.解决在对对象流进行读写操作时所引发的问题。


序列化的特点:

1.如果某个类能够被序列化,其子类也可以被序列化。如果该类有父类,则分两种情况来考虑,如果该父类已经实现了可序列化接口。则其父类的相应字段及属性的处理和该类相同;如果该类的父类没有实现可序列化接口,则该类的父类所有的字段属性将不会序列化

2.声明为static和transient类型的成员数据不能被序列化。因为static代表类的状态, transient代表对象的临时数据。

3.相关的类和接口:在java.io包中提供的涉及对象的序列化的类与接口有ObjectOutput接口、ObjectOutputStream类、ObjectInput接口、ObjectInputStream类。


Demo

这是一个基础类User

package com.test;
import java.io.Serializable;

public class User implements Serializable {

    private int userId;
    private String userName;
    private String userSex;
    private int userAge;

    public int getUserAge() {
       return userAge;
    }

    public void setUserAge(int userAge) {
       this.userAge = userAge;
    }

    public int getUserId() {
       return userId;
    }

    public void setUserId(int userId) {
       this.userId = userId;
    }

    public String getUserName() {
       return userName;
    }

    public void setUserName(String userName) {
       this.userName = userName;
    }

    public String getUserSex() {
       return userSex;
    }

    public void setUserSex(String userSex) {
       this.userSex = userSex;
    }

    @Override
    public String toString() {
       return this.getUserId() + "   " + this.getUserName() + "   "
              + this.getUserSex() + "    " + this.getUserAge();
    }
}


测试类:

package com.test;


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

public class Test {

    /**
     *将对象序列化到磁盘文件中
     */
    public static void writeObject(Object o) throws Exception{

       File f = new File("f:\\user.tmp");
       if(f.exists()){
           f.delete();
       }

       FileOutputStream os = new FileOutputStream(f);

       //ObjectOutputStream 核心类
       ObjectOutputStream oos = new ObjectOutputStream(os);
       oos.writeObject(o);
       oos.close();
       os.close();
    }

    /**
     *反序列化,将磁盘文件转化为对象
     */
    public static User readObject(File f) throws Exception{

       InputStream is = new FileInputStream(f);

       //ObjectOutputStream 核心类
       ObjectInputStream ois = new ObjectInputStream(is);
       return (User)ois.readObject();
    }

    public static void main(String[] args) throws Exception{
    	
       /*****************将对象序列化***************/
       User user = new User();
       user.setUserId(1);
       user.setUserName("张艺谋");
       user.setUserSex("男");
       user.setUserAge(50);
       Test.writeObject(user);

       
       /*****************将对象序反列化***************/     
       User user2 = Test.readObject(new File("f:\\user.tmp"));
       System.out.println(user2);
    }
}

输出:

JAVA序列化和反序列化_第1张图片

这是user.tmp里的内容:

JAVA序列化和反序列化_第2张图片


以上我们先将User对象序列化输出到文件中,后将文件中的流反序列化生成一个对象实例,在这里:

(1)ObjectOutput接口:它继承DataOutput接口并且支持对象的序列化,其内的writeObject()方法实现存储一 个对象。

(2)ObjectInput接口:它继承DataInput接口并且支持对象的序列化,其内的readObject()方法实现读取一个对象。
(3)ObjectOutputStream类:它继承OutputStream类并且实现ObjectOutput接口。利用该类来实现将对象存储 (调用ObjectOutput接口中的writeObject()方法)。

(4)ObjectInputStream类:它继承InputStream类并且实现ObjectInput接口。利用该类来实现读取一个对象(调用 ObjectInput接口中的readObject()方法)。


注意:

如果出现父类,对父类的处理:

如果父类没有实现序列化接口,则其必须有默认的构造函数(即没有参数的构造函数)。否则编译的时候就会报错。在反序列化的时候,默认构造函数会被调用。但是若把父类标记为可以序列化,则在反序列化的时候,其默认构造函数不会被调用。这是为什么呢?这是因为Java 对序列化的对象进行反序列化的时候,直接从流里获取其对象数据来生成一个对象实例,而不是通过其构造函数来完成。


以上的内容比较浅显,笔者用到的和JAVA序列化有关的技术不多,如有问题,欢迎大家指出!

你可能感兴趣的:(JAVA)