Java序列化和反序列化

两个Java进程进行通信时实现进程间的对象传送需要Java序列化与反序列化。

对象(object)是类(class)的一个实例(instance)。一个类中包含了变量(field)和函数(method)两个部分。同一个 类的不同对象只是变量不同,所以Java API序列化过程中只保存了对象的变量部分。同样,由于静态变量(static field)是由同一个类的各个对象共用的,所以序列化过程中也不保存。

1、序列化和反序列化:Java序列化是指把Java对象转换为字节序列的过程,而Java反序列化是指把字节序列恢复为Java对象的过程

1.1、序列: 把对象转换成有序字节流,以便在网络上传输或者保存在本地磁盘中。对象序列化的最主要的用处就是在传递和保存对象的时候,保证对象的完整性和可传递性。

1.2、反序列化:把字节序列恢复为Java对象的过程。

2Java序列化的好

1)永久性保存对象,保存对象的字节序列到本地文件或者数据库中;

2)通过序列化以字节流的形式使对象在网络中进行传递和接收;

3)通过序列化在进程间传递对象。

3、实现序列化的要求:

只有实现了Serializable或Externalizable接口的类的对象才能被序列化,否则抛出异常!实现接口无须实现任何方法,只是表明该类的实例时可以序列化的。Externalizable接口继承自 Serializable接口,实现Externalizable接口的类完全由自身来控制序列化的行为,而仅实现Serializable接口的类可以 采用默认的序列化方式 。

在Java API中,对象序列化接口主要由两个类提供:ObjectOutputStream,ObjectInputStream。

4、序列化实现

4.1、序列化

1)创建一个对象输出流,它可以包装一个其它类型的目标输出流,如文件输出流;

ObjectOutputStream  oos = new ObjectOutputStream(new FileOutputStream("D:/Person.txt"));

2)调用输出流ObjectOutputStream对象的writeObject()方法写对象。

oos.writeObject(person);

4.2、反序列化

1)创建ObjectOutputStream流对象,是一个处理流;

ObjectInputStream in = new ObjectInputStream(new FileInputStream(

                new File("D:/Person.txt")));

2)调用ObjectInputStream对象的readObject()方法读取流中的对象,返回一个object类型的Java对象。

Person person = (Person) in.readObject();

5、自定义序列化

在属性前面加transient关键字,可以指定Java序列化时无需理会该属性。被其修饰的属性被完全隔离在序列化机制之外,恢复的时候无法取得该值。

6、serialVersionUID的作用:

6.1、serialVersionUID是对类进行版本控制的,Java的序列化机制是通过判断类的serialVersionUID来验证版本一致性的。在进行反序列化时,JVM会把传来的字节流中的serialVersionUID与本地相应实体类的serialVersionUID进行比较,如果相同就认为是一致的,可以进行反序列化,否则就会出现序列化版本不一致的异常,即是InvalidCastException。

6.2、serialVersionUID有两种生成方式:

1)默认的1L,比如:private static final long serialVersionUID = 1L;

2)根据类名、接口名、成员方法及属性等来生成一个64位的哈希字段。

参考:

https://blog.youkuaiyun.com/gsn2167/article/details/78095045

https://www.cnblogs.com/wxgblogs/p/5849951.html

 

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

public class WriteObject
{
    public static void main(String[] args)
    {
        SerializePerson(); // 序列化Person对象
        DeserializePerson();// 反序列化

    }

    private static void SerializePerson()
    {
        ObjectOutputStream oos = null;
        try
        {
            // 创建一个输出流
            oos = new ObjectOutputStream(new FileOutputStream("D:/Person.txt"));
            Person person = new Person("孙悟空", 500, "男");
            // 将person对象写入输出流
            oos.writeObject(person);
        } catch (IOException ex)
        {
            ex.printStackTrace();
        } finally
        {
            try
            {
                if (oos != null)
                {
                    System.out.println("Person对象序列化成功!");
                    oos.close();
                }
            } catch (IOException ex)
            {
                ex.printStackTrace();
            }
        }
    }

    private static void DeserializePerson()
    {
        ObjectInputStream ois = null;
        try
        {
            // 创建一个输入流
            ois = new ObjectInputStream(new FileInputStream("D:/Person.txt"));
            // 从输入流读取Java对象,并转化为Person
            Person person = (Person) ois.readObject();
            System.out.println("名字:" + person.getName() + ",年龄:"
                    + person.getAge() + ",性别:" + person.getSex());
        } catch (Exception ex)
        {
            ex.printStackTrace();
        } finally
        {
            try
            {
                if (ois != null)
                {
                    System.out.println("反序列化成功!");
                    ois.close();
                }
            } catch (IOException ex)
            {
                ex.printStackTrace();
            }
        }
    }
}

class Person implements Serializable
{
    private static final long serialVersionUID = -5809782578272943999L;
    private String name;
    private int age;
    private transient String sex;// 自定义,不序列化

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

    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 getSex()
    {
        return sex;
    }

    public void setSex(String sex)
    {
        this.sex = sex;
    }

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

import java.io.Serializable;
import java.text.MessageFormat;

public class TestObjSerializeAndDeserialize
{
    public static void main(String[] args) throws Exception
    {
        SerializePerson(); // 序列化Person对象
        Person p = DeserializePerson(); // 反序列Perons对象
        System.out.println(MessageFormat.format("name={0},age={1},sex={2}", p.getName(), p.getAge(), p.getSex()));
    }

    /*
     * 步骤一:创建一个对象输出流,它可以包装一个其它类型的目标输出流,如文件输出流:
     * ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("D:\\object.out"));
     * 步骤二:通过对象输出流的writeObject()方法写对象:
     * oos.writeObject(new User("xuliugen", "123456", "male"));
     */
    private static void SerializePerson() throws FileNotFoundException,IOException
    {
        Person person = new Person();
        person.setName("asd");
        person.setAge(26);
        person.setSex("男");
        // ObjectOutputStream,创建一个流对象,比如文件输出流对象
        // 对象输出流,将Person对象存储到E盘的Person.txt文件中,完成对Person对象的序列化操作
        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(
                new File("D:/Person.txt")));
        out.writeObject(person);
        System.out.println("Person对象序列化成功!");
        out.close();
    }

    /*
     * 步骤一:创建一个对象输入流,它可以包装一个其它类型输入流,如文件输入流:
     * ObjectInputStream ois= new ObjectInputStream(new FileInputStream("object.out"));
     * 步骤二:通过对象输出流的readObject()方法读取对象:User user = (User) ois.readObject();
     */
    private static Person DeserializePerson() throws Exception, IOException
    {
        ObjectInputStream in = new ObjectInputStream(new FileInputStream(
                new File("D:/Person.txt")));
        Person person = (Person) in.readObject();
        System.out.println("Person对象反序列化成功!");
        return person;
    }

}

class Person implements Serializable
{
    /**
     * 序列化ID
     */
    private static final long serialVersionUID = -5809782578272943999L;
    private int age;
    private String name;
    private String sex;

    public int getAge()
    {
        return age;
    }

    public String getName()
    {
        return name;
    }

    public String getSex()
    {
        return sex;
    }

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

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

    public void setSex(String sex)
    {
        this.sex = sex;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值