美文网首页
序列化与反序列化

序列化与反序列化

作者: Jycoding | 来源:发表于2022-07-22 13:38 被阅读0次

序列化是指将对象的状态信息转换为可以存储或传输形式的过程.在序列化期间,对象将其当前状态写入到临时或持久性存储区.以后可以通过从存储区中读取或者反序列化对象的状态,重新创建该对象.

序列化:利用ObjectOutputStream,把对象的信息,按照固定的格式转成一串字节值输出并持久保存到磁盘

反序列化:利用ObjectInputStream,读取磁盘中之前序列化好的数据,重新恢复成对象

需要序列化的文件必须实现Serializable接口,用来启用序列化功能

不需要序列化的数据可以修饰成static,原因:static资源属于类资源,不随着对象被序列化输出

每一个被序列化的文件都有一个唯一的id,如果没有添加此id,编译器会自动根据类的定义信息计算产生一个

在反序列化时,如果和序列化的版本号不一致,无法完成反序列化

常用与服务器之间的数据传输,序列化成文件,反序列化读取数据

常用使用套接字流在主机之间传递对象

不需要序列化的数据也可以被修饰成transient(临时的),只在程序运行期间在内存中存在,不会被序列化持久保存

序列化:ObjectOutputStream

ObjectOutputStream 将 Java 对象的基本数据类型写入 OutputStream,通过在流中使用文件可以实现对象的持久存储。如果流是网络套接字流,则可以在另一台主机上或另一个进程中重构对象。

构造方法:

ObjectOutputStream(OutputStream out)

创建写入指定 OutputStream 的 ObjectOutputStream

普通方法:

writeObject(Object obj)

将指定的对象写入 ObjectOutputStream

反序列化:ObjectInputStream

ObjectInputStream对以前使用ObjectOutputStream写入的基本数据和对象进行反序列化重构对象。

构造方法:

ObjectInputStream(InputStream in) 创建从指定 InputStream 读取的 ObjectInputStream

普通方法:

readObject() 从 ObjectInputStream 读取对象

package cn.tedu.serializable;

import java.io.Serializable;

/**本类用来封装学生类*/

/**

* 如果本类想要完成序列化,必须实现可序列化接口,否则会报错:

* 报错信息:java.io.NotSerializableException: cn.tedu.serializable.Student

* Serializable接口是一个空接口,里面一个方法都没有,作用是用来当做标志,标志这个类可以序列化/反序列化

* */

public class Student implements Serializable{

/**需要给每个进行序列化的文件分配唯一的UID值*/

//The serializable class Student does not declare a static final serialVersionUID field of type long

//private static final long serialVersionUID = 1L;

private static final long serialVersionUID = -3193364654654535741L;

//1.定义学生的相关属性 + private封装

private String name;//姓名

private int age;//年龄

private String addr;//地址

private char gender;//性别

/**自动创建构造方法:右键-->Source-->Generate Constructor using Fields...*/

//2.创建无参构造--必须手动提供无参构造,否则会被含参构造覆盖

public Student() {

System.out.println("我是Student的无参构造");

}

//3.创建全参构造

public Student(String name,int age,String addr,char gender) {

super();//默认调用父类的无参构造

this.name = name;

this.age = age;

this.addr = addr;

this.gender = gender;

System.out.println("我是Student的全参构造");

}

//4.属性封装后,需要本类提供公共的属性访问与设置方式get()&set()

/**自动创建get()&set(),右键-->Source-->Generate Getters and Setters...*/

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 getAddr() {

return addr;

}

public void setAddr(String addr) {

this.addr = addr;

}

public char getGender() {

return gender;

}

public void setGender(char gender) {

this.gender = gender;

}

//打印结果:cn.tedu.serializable.Student@4c873330-->地址值

//想看对象的属性值,原因是想查看序列化后对象的属性,需要重写toString()

//5.重写toString()

//自动生成toString()--右键-->Source-->Generate toString()

@Override

public String toString() {

return "Student [name=" + name + ", age=" + age + ", addr=" + addr + ", gender=" + gender + "]";

}

}

package cn.tedu.serializable;

import java.io.FileInputStream;

import java.io.FileNotFoundException;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.ObjectInputStream;

import java.io.ObjectOutputStream;

/**本类用于序列化与反序列化的测试类*/

//序列化:是指把程序中的java对象,永久保存在磁盘中,相当于是写出的过程,方向是out-->ObjectOutputStream

//反序列化:是指把已经序列化在文件中保存的数据,读取/恢复到java程序中的过程,方向是in-->ObjectInputStream

public class TestSerializable {

public static void main(String[] args) {

//method();//本方法用来完成序列化的功能

method2();//本方法用于完成反序列化功能

}

/**反序列化方法*/

public static void method2() {

//声明在本方法内都生效的局部变量,局部变量需要初始化,默认值是null

ObjectInputStream in = null;

try {

//1.创建ObjectInputStream流对象来完成反序列化

in = new ObjectInputStream(new FileInputStream("D://ready//1.txt"));

//2.通过流对象反序列化生成指定对象

Object o = in.readObject();

System.out.println(o);

System.out.println("恭喜您!反序列化成功!");

} catch (Exception e) {

System.out.println("很抱歉!反序列化失败!");

e.printStackTrace();

} finally {//一定会执行的代码块写释放资源的代码

try {

//3.释放资源

in.close();

} catch (IOException e) {

e.printStackTrace();

}

}

}

/**序列化方法*/

public static void method() {

//声明在本方法内都生效的局部变量,局部变量需要初始化,默认值是null

ObjectOutputStream out = null;

try {

//1.创建ObjectOutputStream流对象来完成序列化

out = new ObjectOutputStream(new FileOutputStream("D://ready//1.txt"));

//2.指定要序列化(输出)的对象

Student obj = new Student("海绵宝宝",3,"大海底部",'男');

//3.通过OOS流对象来序列化输出Student对象

out.writeObject(obj);

System.out.println("恭喜你!序列化成功!");

} catch (IOException e) {

System.out.println("很抱歉!序列化失败!");

e.printStackTrace();

}finally {//关流的操作要放在finally{}中--因为此代码块一定会执行

try {

//4.关流操作

out.close();

} catch (IOException e) {

e.printStackTrace();

}

}

}

}

测试报错NotSerializableException:

报错原因:要序列化对象所在的类并没有实现序列化接口

解决方案:实现序列化接口

6 测试报错InvalidClassException:

报错原因:本次反序列化时使用的UID与序列化时的UID不匹配

解决方案:反序列化时的UID与序列化时的UID要保持一致,或者测试时一次序列操作对应一次反序列化操作,否则不匹配就报错

注:IDEA中设置自动生成serialVersionUID的提示:

相关文章

网友评论

      本文标题:序列化与反序列化

      本文链接:https://www.haomeiwen.com/subject/dppmirtx.html