目录

一、基本概念

1、定义

2、作用

 二、序列化和反序列化的优缺点

1、优点

2、缺点

三、序列化使用场景

四、序列化与反序列化的注意事项

五、代码案例


一、基本概念

1、定义

序列化:java序列化是指对java对象转换为字节序列的过程

反序列化:java反序列化是指把字节序列恢复java对象的过程 

2、作用

序列化的作用:在传递和保存对象时,保存对象的完整性和可传递性

对象转换为有序字节流,可以在网络上传输或则保存在本地文件中。

反序列化的作用:根据字节流中保存的对象状态及描述信息,通过反序列化重建对象。

Java protobuf自定义序列化和反序列化 java序列化和反序列化作用_序列化

 二、序列化和反序列化的优缺点

1、优点

  • 将对象转为字节流存储在磁盘上,当JVM停机的时候,字节流还会磁盘上等待,等下一次JVM启动,把序列化的对象,通过反序列化转为原来的对象,并且序列化的二进制序列减少存储空间
  • 序列化转为字节流形式的对象可以进行网络传输
  • 通过序列化可以在进程之间传递对象

2、缺点

  • 无法跨语言
  • 序列化后流的长度比通过缓冲区处理要大得多
  • 序列化性能太低

三、序列化使用场景

1、分布式传递对象,或则网络传输,需要序列化

2、我调用你的jvm的方法,结果返回到我的jvm上进行处理

3、序列化可以保持对象的状态

4、数据传输并复原。在将j2ee中页面和后端使用的比较多。

5、远程调用,分布式存储,缓存存储

6、像银行卡,密码这些字段不能被序列化

四、序列化与反序列化的注意事项

1、java序列化的方式

  • 实现Serializable接口,可以自定义writeObject,readObject,writeReplace,readResolve方法,会通过反射调用
  • 实现Externalizable接口,需要实现writeExternal,readExternal方法

2、序列化ID问题

虚拟机是否允许反序列化,不仅取决于类路径和功能代码是否一致,一个非常重要的一点是两个类序列化ID是否一致(就是private static final long serialVersionUID = 1L;)

3、静态字段不会序列化

序列化时不保存静态变量,这是因为序列化保存的是对象的状态。静态变量是属于类的状态,因此序列化不保存静态变量。

4、transient

transient代表对象的临时数据。

如果你不想让对象中的某个成员被序列化可以在定义它的时候加上 transient 关键字进行修饰,这样,在对象被序列化时其就不会被序列化。

transient 修饰过的成员反序列化后将赋予默认值,即 0 或 null。

5、父类的序列化

当一个父类序列化,子类自动实现序列化,而子类实现Serializable接口,父类也需要实现Serializable接口

6、当一个对象的实例变量引用其他对象,序列化该对象时也把引用对象进行序列化

7、并非所有的对象都可以序列化

(1)安全方面的原因,比如一个对象拥有private,public等field,对于一个要传输的对象,比如写到文件,或者进行RMI传输等等,在序列化进行传输的过程中,这个对象的private等域是不受保护的;

(2)资源分配方面的原因,比如socket,thread类,如果可以序列化,进行传输或者保存,也无法对他们进行重新的资源分配,而且,也是没有必要这样实现

8、序列化解决深拷贝问题

如果一个对象的成员变量是一个对象,那么这个对象的数据成员也会被保存,这是用序列化深拷贝的重要原因。

五、代码案例

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;

import java.io.Serializable;

/**
 * Describe: 用户实体
 * Author: wang zhaoxian
 * DATE: 2021/8/15.
 */
@AllArgsConstructor
@Data
@ToString
@NoArgsConstructor
public class User implements Serializable {

    public static final long serialVersionUID = 1L;
    private Integer id;
    private String name;
    private transient String password;
}
package com.xian.transi;

import com.xian.dto.User;
import org.junit.Test;

import java.io.*;

/**
 * Describe:
 * Author: wang zhaoxian
 * DATE: 2021/8/21.
 */
public class TransientTest {

    @Test
    public void transientTest(){
        try {
            this.SerializableUser();
            this.DeSerializableUser();
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }


    public void SerializableUser() throws IOException {
        User user = new User(1,"zhaoxian","123456");
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("D://data.txt"));
        oos.writeObject(user);
        oos.close();
        System.out.println("普通序列化:userName:"+user.getName());
        System.out.println("transient关键字序列化:password:"+user.getPassword());
        /**
         * 普通序列化:userName:zhaoxian
         * transient关键字序列化:password:123456
         */
    }

    public void DeSerializableUser() throws IOException, ClassNotFoundException {
        File file = new File("D://data.txt");
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));
        User user = (User)ois.readObject();
        System.out.println("普通反序列化:userName:"+user.getName());
        System.out.println("transient关键字反序列化:password:"+user.getPassword());
        /**
         * 普通反序列化:userName:zhaoxian
         * transient关键字反序列化:password:null
         */
    }
}