对象序列化流与反序列化流
对象序列化流与反序列化流
什么是序列化与反序列化
=java序列化,就是指吧java对象转换为字节序列的过程。而反序列自然就是将字节对象恢复为java对象。==
这样做的意义在哪呢?对象进行序列化,会转换为字节流,这样在网络上传输,或者是进行保存为本地文件都是非常方便的。反序列很明显就是进行对象的重构。
其实你可以和通信联系在一起。==网络上的文本,图片,视频,音频都是通过二进制进行传输的,我们的java所创建的对象在传输的时候也应该进行序列化,转换为字节流,然后通过网络,io传入,当我们的对象序列传输完成后,对方进行反序列化,就可以读取到数据内容。==
对象序列化流( ObjectOutputStream)
api对这个类有很多的说明,主要说明
public class ObjectOutputStreamextends OutputStreamimplements ObjectOutput, ObjectStreamConstants
ObjectOutputStream 将 Java 对象的基本数据类型和图形写入 OutputStream。可以使用 ObjectInputStream 读取(重构)对象。通过在流中使用文件可以实现对象的持久存储。如果流是网络套接字流,则可以在另一台主机上或另一个进程中重构对象。
看一下简单使用
首先我们需要一个对象类
package io_demo;
import java.io.Serializable;
public class Student implements Serializable {
private String sid;
private String name;
int age;
private String address;
public Student()
{
}
public Student(String sid, String name, int age, String address) {
this.sid = sid;
this.name = name;
this.age = age;
this.address = address;
}
public String getSid() {
return sid;
}
public void setSid(String sid) {
this.sid = sid;
}
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 getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
然后测试主类
package io_demo;
import java.io.*;
public class IoDemo_23 {
//对象序列化流
// 构造方法
// ObjectOutputStream(OutputStream out)
public static void main(String args[]) throws IOException {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("E:\\java_doc\\src\\io_demo\\jgdabc.txt"));
Student s = new Student("001","刘备",28,"汉中");
oos.writeObject(s);//将对象序列化()
oos.close();
}
}
为什么Student需要实现Serializable,api有说明
只能将支持 java.io.Serializable 接口的对象写入流中。每个 serializable 对象的类都被编码,编码内容包括类名和类签名、对象的字段值和数组值,以及从初始对象中引用的其他所有对象的闭包。
为什么没有具体实现?
因为这个接口本身没有具体实现,==我们不要要实现什么,这个只是作为一个标识而已。==
对象反序列化流(.ObjectInputStream)
public class ObjectInputStream
extends InputStream
implements ObjectInput, ObjectStreamConstants
说明如下
ObjectInputStream反序列化先前使用ObjectOutputStream编写的原始数据和对象。
ObjectOutputStream和ObjectInputStream可以分别为与FileOutputStream和FileInputStream一起使用的对象图提供持久性存储的应用程序。 ObjectInputStream用于恢复先前序列化的对象。 其他用途包括使用套接字流在主机之间传递对象,或者在远程通信系统中进行封送和解组参数和参数。
首先还是原来的Student对象类
package io_demo;
import java.io.Serializable;
public class Student implements Serializable {
private String sid;
private String name;
int age;
private String address;
public Student()
{
}
public Student(String sid, String name, int age, String address) {
this.sid = sid;
this.name = name;
this.age = age;
this.address = address;
}
public String getSid() {
return sid;
}
public void setSid(String sid) {
this.sid = sid;
}
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 getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
对的,==你虽然是从文件中读取,但是如果你不使用构建的对象的话。是绝对无法成功进行反序列化的。==
主要的测试代码
package io_demo;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.ObjectInputStream;
//反序列化ObiectreadObject() 进行读取来反序列化
public class IoDemo_24 {
public static void main(String args[]) throws IOException, ClassNotFoundException {
//实现对象反序列化流
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("E:\\java_doc\\src\\io_demo\\jgdabc.txt"));
Object o = ois.readObject();
Student s = (Student)o;
System.out.println(s.getName()+","+s.getAge());
ois.close();
}
}
这样感觉有时候很像加密与解密的样子。
如果在反序列话的时候原来对象类有修改?
我现在就修改一个属性。我让age属性权限有所变化,变为私有属性
**结果反序列化就报错了,为什么?你看报错 **
再清晰一点就是
local class incompatible: stream classdesc serialVersionUID = -8624680451455869930, local class serialVersionUID = 6474701452341618882
serialVersionUID是什么?(为什么修改对象类会反序列化失败?)
==serialVersionUID是序列化的时候会生成的一个的版本标识,。当我们对对象进行修改后,那么这个序列化的版本标识的值就会与之前的不一样了。这样会导致字节流的版本标识与本地的版本标识不一样,不一样就会反序列化失败。==
解决修改对象类修改反序列化失败的问题
==我们就自己定义一个常量。让这个版本标识符不再变化==
注意,一定是在对象类中,不是在测试类。
不想让某些属性被序列化?
这样就可以
- 点赞
- 收藏
- 关注作者
评论(0)