2.4 对象的序列化与反序列化

本文介绍了Java中对象序列化和反序列化的概念、作用以及使用场景。通过示例代码展示了如何使用ObjectOutputStream和ObjectInputStream进行序列化和反序列化操作,讨论了transient和static关键字在序列化过程中的影响,并提到了serialVersionUID在版本控制中的作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.简介
(1).序列化
把对象转换为字节序列的过程称为对象的序列化。

(2).反序列化
把字节序列恢复为对象的过程称为对象的反序列化。

(3).为什么要进行序列化或者反序列化
程序在运行时实例化出对象,这些对象存在于内存中,随着程序运行停止而消失,但如果想把某些对象(一般都是各不相同的属性)保存下来或者传输给其它进程,在程序终止运行后这些对象仍然存在,可以在程序再次运行时读取这些对象的信息,或者在其他程序中利用这些保存下来的对象信息恢复成实例对象。这种情况下就要使用对象的序列化和反序列化。

(4).使用场景

  • 需要把内存中的对象保存到文件或者数据库中时
  • 需要通过套接字在网络上传输对象时
  • 需要通过RMI传输对象时

2.序列化
(1).SerializeDemo
ObjectOutputStream类用来序列化一个对象,如下的SerializeDemo例子实例化了一个Employee对象,并将该对象序列化到一个文件中。

public class Employee implements Serializable {
    public String name;

    public transient int age;

    public static String sex;

    public final String address = "南京";

	/*
     * static修饰的sex不能由构造方法初始化
     * final修饰的address在定义时必须初始化,因此不需要由构造函数初始化
     */
    public Employee(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public void sayHello() {
        System.out.println("Hello everyone,I am " + name);
    }

	//get和set方法
}
public class SerializeDemo {
    public static void main(String[] args) {
        Employee employee = new Employee("steven", 30);
        try {
            FileOutputStream fileOutputStream = new FileOutputStream("D:\\代码\\project\\app\\src\\employee.ser");
            ObjectOutputStream oos = new ObjectOutputStream(fileOutputStream);
            oos.writeObject(employee);
            oos.close();
            fileOutputStream.close();
            System.out.printf("Serialized data is saved in employee.ser");
        } catch (IOException ioException) {
            ioException.printStackTrace();
        }
    }
}

(2).执行结构

Serialized data is saved in employee.ser

3.反序列化
(1).DeserializeDemo

public class DeserializeDemo {
    public static void main(String[] args) {
        Employee employee = null;
        try {
            FileInputStream fileInputStream = new FileInputStream("D:\\代码\\project\\app\\src\\employee.ser");
            ObjectInputStream ois = new ObjectInputStream(fileInputStream);
            employee = (Employee) ois.readObject();
            ois.close();
            fileInputStream.close();
        } catch (IOException ioException) {
            ioException.printStackTrace();
            return;
        } catch (ClassNotFoundException c) {
            System.out.println("Employee class not found");
            c.printStackTrace();
            return;
        }
        System.out.println("Deserialized Employee Start......");
        System.out.println("name:" + employee.name);
        System.out.println("age:" + employee.age);
        System.out.println("sex:" + employee.sex);
        System.out.println("address:" + employee.address);
        employee.sayHello();
        System.out.println("Deserialized Employee End......");
    }
}

(2).执行结果

Deserialized Employee Start......
name:steven
age:0
sex:null
address:南京
Hello everyone,I am steven
Deserialized Employee End......

4.总结
(1).Serializable
没有实现Serializable接口的类无法序列化,否则会抛以下异常。

java.io.NotSerializableException: Employee
	at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1184)
	at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:348)
	at SerializeDemo.main(SerializeDemo.java:11)

(2).transient

  • 被transient关键字修饰的属性不会被序列化(不管有没有和static和final联合使用),而是使用该属性类型的默认值,如Employee中被transient关键字修饰的int类型的age,初始化时设置的值为30,反序列化之后值为0。
  • transient只能修饰属性,不能修饰方法和类。

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

(4).static
被static关键字修饰的属性不参与序列化,因为静态变量不是对象的一部分,而是属于类。

(5).final
final变量值参与序列化。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值