栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

【序列化】lipp chan学习笔记

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

【序列化】lipp chan学习笔记

序列化与反序列化
一、目的

为了方便对象IO传输

1.1 作用

当两个进程在远程通信时候,可以发送各种类型的数据,包括jpg、mp4、mp3等媒体文件,这些数据会以二进制序列的形式进行传送。当两个java进程在通信时候,java需要序列化和反序列化进行进程间的对象传送。
例如发送方需要将java对象序列化成二进制字节序列,IO传输;接收方通过二进制字节序列读取出发送方传递的java对象。


二、序列化:将 Java 对象转换成字节流的过程
2.1 序列化过程:
是指把一个 Java 对象变成二进制内容,实质上就是一个 byte[]。
因为序列化后可以把 byte[] 保存到文件中,
或者把 byte[] 通过网络传输到远程(IO)
,如此就相当于把 Java 对象存储到文件或者通过网络传输出去了。
2.2 重点
Java 对象要能序列化,必须实现一个特殊的java.io.Serializable接口,
接口是一个标识空接口,没有定义任何方法,就是为了标识对象可以序列化。

如果要序列化的某些对象未实现java.io.Serializable接口,则此方法将引发NotSerializableException。

三、反序列化:将字节流转换成 Java 对象
3.1 反序列化过程:
把一个二进制内容(也就是 byte[] 数组)变回 Java 对象。
通过反序列化,保存到文件中的 byte[] 数组又可以“变回” Java 对象,
或者从网络上读取 byte[] 并把它“变回” Java 对象。
3.2 作用
  • 以对象形式将数据存储到磁盘上,例如Redis存储对象列表。
  • 将程序状态保存在磁盘上,例如将巫师三存档。
  • 通过网络以表单对象发送数据,例如在聊天app以对象形式发送信息。
四、序列化工作原理
上文说到,我们只需要将对象实现序列化标识接口,
该对象就有资格进行序列化。
真正的序列化对象,jvm帮我们进行该类的对象写入持久性存储
或通过网络进行读取。

当然我们也可以通过ObjectInputStream和ObjectOutputStream对象IO流类实现序列化和反序列化操作。

五、serialVersionUID常数
serialVersionUID 是一个常数,用于唯一标识可序列化类的版本。
从输入流构造对象时,JVM 在反序列化过程中检查此常数。如
果正在读取的对象的 serialVersionUID 与类中指定的序列号不同,
则 JVM 抛出InvalidClassException。
这是为了确保正在构造的对象与具有相同 serialVersionUID 的类兼容。

serialVersionUID 是可选的。如果不显式声明,Java 编译器将自动生成一个。

为什么要显示声明serialVersionUID?

因为java编译器会对要序列化的java对象跟据器类的元素计算UID,有一个改变,
serialVersionUID会随之改变。那如果,一个程序将某个对象序列化到文件中,
没有为其声明显式UID,那更新类后,比如添加个有参构造函数,
那自动生成的UID都变了,那先前序列化的java对象UID都不同,就没法反序列化成功了。
六、瞬时变量 transient
如果成员变量不需要序列化,则可以将其标记为瞬态。这意味着在序列化对象时不会存储 瞬时变量的值。 ## 七、例子 Student类
package day627.serial;

import java.io.Serializable;

public class Student implements Serializable {
	//显式UID
	private static final long serialVersionUID = 1014100089306623762L;
	// 姓名
	private String name;
	// 年龄
	//将年龄设置为瞬时变量
	private transient Integer age;

	public Student() {
	}

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

	public String getName() {
		return name;
	}

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

	public Integer getAge() {
		return age;
	}

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

	@Override
	public String toString() {
		// 优化toString方法
		StringBuilder sb = new StringBuilder();
		sb.append("[").append("name = ").append(this.name).append(", ").append("age =").append(this.age).append("]");
		return sb.toString();
	}

}

测试类

package day627.serial;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;

public class Test01 {
	public static void main(String[] args) throws Exception {
		Student s = new Student();
		System.out.println(s);
//创建对象操作流 --> 序列化
		ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("C:\lipp\company\obj.txt"));
//创建集合,且添加学生对象
		ArrayList list = new ArrayList();
		list.add(new Student("悔创阿里杰克马", 51));
		list.add(new Student("会点一点长几颗", 26));
		list.add(new Student("容颜老去蒋青青", 32));
		list.add(new Student("将里最丑刘一飞", 27));
//将集合写入到文件
		oos.writeObject(list);
//创建对象输入流 --> 反序列化
		ObjectInputStream ois = new ObjectInputStream(new FileInputStream("C:\lipp\company\obj.txt"));
//读取数据
		Object o = ois.readObject();
//向下转型
		ArrayList al = (ArrayList) o;
//遍历集合
		for (int i = 0; i < al.size(); i++) {
//根据索引取出集合的每一个元素
			Student stu = al.get(i);
			System.out.println(stu);
		}
	}
}

result

[name = null, age =null]
[name = 悔创阿里杰克马, age =null]
[name = 会点一点长几颗, age =null]
[name = 容颜老去蒋青青, age =null]
[name = 将里最丑刘一飞, age =null]

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/995558.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号