Java序列化——Serializable和Externalizable

本文深入探讨Java中的序列化机制,包括Serializable和Externalizable接口的使用,以及serialVersionUID的作用。通过具体示例,展示了如何实现对象的序列化和反序列化过程。
摘要由CSDN通过智能技术生成

Java序列化——Serializable和Externalizable

1. 继承Serializable接口


import java.io.Serializable;

/**
 * @author gyh
 * @csdn https://blog.csdn.net/qq_40788718
 * @date 2020/8/12 22:51
 */

public class User implements Serializable {

    private static final long serialVersionUID = 1L ;

    private String name ;

    private Integer age ;

    public User(){

    }

    public User(String name , Integer age){
        this.name = name ;
        this.age = age ;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

import java.io.*;

/**
 * @author gyh
 * @csdn https://blog.csdn.net/qq_40788718
 * @date 2020/8/12 22:53
 */

public class SerializableTest {

    public static void main(String[] args) throws IOException, ClassNotFoundException {
        File file = new File("F:\\2.txt") ;
        if (!file.exists()){
            file.createNewFile();
        }
        serializeUser() ;
        unserializeUser();
    }

    private static void unserializeUser() throws IOException, ClassNotFoundException {
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("F:\\2.txt"));
        User user = (User) ois.readObject();
        System.out.println(user.toString());
        System.out.println("反序列化成功");
        ois.close();
    }

    private static void serializeUser() throws IOException {
        User user = new User("guoyuhang" , 22) ;
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("F:\\2.txt")) ;
        oos.writeObject(user) ;
        oos.close() ;
        System.out.println("序列化成功");
    }
}
序列化成功
User{name='guoyuhang', age=22}
反序列化成功
 sr serializable.User;.V? L aget Ljava/lang/Integer;L namet Ljava/lang/String;xpsr java.lang.Integer鉅亣8 I valuexr java.lang.Number啲?斷?  xp   t 	guoyuhang

2. 继承Externalizable接口


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

/**
 * @author gyh
 * @csdn https://blog.csdn.net/qq_40788718
 * @date 2020/8/12 23:03
 */

public class EUser implements Externalizable {

    private static final long serialVersionUID = 2106328197756487707L ;

    private String name ;

    private Integer age ;

    private int type ;

    /**
     * 保留无参构造
     */
    public EUser() {
    }

    public EUser(String name, Integer age, int type) {
        this.name = name;
        this.age = age;
        this.type = type;
    }

    /**
     * 需要注意的是引用类型使用writeObject
     */
    @Override
    public void writeExternal(ObjectOutput out) throws IOException {
        out.writeObject(name);
        out.writeObject(age);
        out.writeInt(type);
    }

    @Override
    public String toString() {
        return "EUser{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", type=" + type +
                '}';
    }

    /**
     * 需要注意的是保证读取的顺序和writeExternal中写入的顺序相同
     */
    @Override
    public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
        name = (String) in.readObject();
        age = (Integer) in.readObject();
        type = in.readInt() ;
    }
}

序列化成功
EUser{name='guoyuhang', age=22, type=3}
反序列化成功
 sr serializable.EUser;.V?  xpt 	guoyuhangsr java.lang.Integer鉅亣8 I valuexr java.lang.Number啲?斷?  xp   w   x

3. serialVersionUID

其目的是序列化对象版本控制,有关各版本反序列化时是否兼容。如果在新版本中这个值修改了,新版本就不兼容旧版本,反序列化时会抛出InvalidClassException异常。如果修改较小,比如仅仅是增加了一个属性,我们希望向下兼容,老版本的数据都能保留,那就不用修改;如果我们删除了一个属性,或者更改了类的继承关系,必然不兼容旧数据,这时就应该手动更新版本号,即SerialVersionUid。

serialVersionUID有两种显示的生成方式:

  • 默认的1L,比如:private static final long serialVersionUID = 1L
  • 根据类名、接口名、成员方法及属性等来生成一个64位的哈希字段,比如:private static final long serialVersionUID = xxxxL;

注意

  • 静态变量不会被序列化。
  • 同时transient关键字修饰的变量也不会序列化,但是反序列化是会被赋为初始值。

4. Serializable和Externalizable的区别

  • 序列化内容:Externalizable自定义序列化可以控制序列化的过程和决定哪些属性不被序列化。而Serializable需要通过Transient关键字来实现哪些不用实例化。
  • Serializable序列化时不会调用默认的构造器,而Externalizable序列化时会调用默认构造器的。但是Serializable会破坏单例模式(因为序列化可以实现深克隆)。
  • 使用Externalizable时,必须按照写入时的确切顺序读取所有字段状态。否则会产生异常。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值