Java 序列化与反序列化
序列化就是Java对象转化为字节序列的过程,反序列化则是把字节序列恢复为Java对象的过程。
网络中的各种通信传输可以传送文字、图片、文件都是以二进制字节的序列进行传输的,因此
如果两个Java进程之间传输对象也需要将对象进行序列化传输和反序列化进行接收。Java的JDK
开发包中提供了将Java对象序列化和反序列化的方法:ObjectOutputStream和ObjectInputStram
ObjectOutputStream中的writeObject(Objec obj)将Java对象进行序列化,把得到的字节序列输出
到一个目标流中;ObjectInputStream的readObject()方法则是将目标流中的字节序列回复为Java
对象。
序列化和反序列化的作用:
1.实现Java对象持久化,将序列化数据保存到本地(硬盘)
2.实现Java对象在网络之间的通讯,将序列化的字节序列通过网络进行传输
在Java中想实现对象的序列化和反序列化很简单,只需要实现Serializable或者Externalizable接口
Serializable就是一个接口没有可实现的方法,默认就会将实现该接口的所有声明的非transient属性
进行序列化;Externalizable接口需要实现writeExternal和readExternal方法,也就是说该接口是一个
需要手动指定哪些属性需要进行序列化。
开始序列化--------------
开始反序列化-------------
1,zhangsan,男
如果实体类没有实现序列化接口程序将抛java.io.NotSerializableException异常
另外在将某个对象序列化的时候实现Serializable接口的时候通常都会添加一个静态
不可改变值的序列化版本号编号,这将是这个序列化对象的唯一标识,如果我们没有
添加,该类会出现警告的信息提示我们添加,但是如果我们不添加系统会默认给该类
指定一个编号,只是我们没看到。但是这样会有一些安全隐患,比如我们将一个对象
持久化到本地,这个时候我们在类中添加一个额外的属性,再进行反序列化的时候将
本地字节序列恢复到对象的时候就会抛java.io.InvalidClassException异常,、
异常信息:core.java.serializable.User; local class incompatible:
stream classdesc serialVersionUID = -9060100527542415407,
local class serialVersionUID = 8511909251520938165
意思就是本地的类和字节序列中的类不是同一个类,因为他们两个类的版本号不一样。
在进行反序列化的时候本地的类是无效的。所以当我们在进行对象序列化的时候一定
要添加上序列化版本号,以防程序抛异常。
序列化就是Java对象转化为字节序列的过程,反序列化则是把字节序列恢复为Java对象的过程。
网络中的各种通信传输可以传送文字、图片、文件都是以二进制字节的序列进行传输的,因此
如果两个Java进程之间传输对象也需要将对象进行序列化传输和反序列化进行接收。Java的JDK
开发包中提供了将Java对象序列化和反序列化的方法:ObjectOutputStream和ObjectInputStram
ObjectOutputStream中的writeObject(Objec obj)将Java对象进行序列化,把得到的字节序列输出
到一个目标流中;ObjectInputStream的readObject()方法则是将目标流中的字节序列回复为Java
对象。
序列化和反序列化的作用:
1.实现Java对象持久化,将序列化数据保存到本地(硬盘)
2.实现Java对象在网络之间的通讯,将序列化的字节序列通过网络进行传输
在Java中想实现对象的序列化和反序列化很简单,只需要实现Serializable或者Externalizable接口
Serializable就是一个接口没有可实现的方法,默认就会将实现该接口的所有声明的非transient属性
进行序列化;Externalizable接口需要实现writeExternal和readExternal方法,也就是说该接口是一个
需要手动指定哪些属性需要进行序列化。
代码演示
package core.java.serializable;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
public class SerializableDemo {
public static void main(String[] args) {
SerializableDemo demo = new SerializableDemo();
User user = new User(1, "zhangsan", "男");
System.out.println("开始序列化--------------");
demo.writeObject(user);
System.out.println("开始反序列化-------------");
User u = (User)demo.readObject();
System.err.println(u.getId() + "," + u.getName() + "," + u.getSex());
}
/**
* 序列化对象
* @param obj
*/
private void writeObject(Object obj){
try {
ObjectOutputStream ots = new ObjectOutputStream(new FileOutputStream(new File("D:/object.txt")));
ots.writeObject(obj);
ots.flush();
ots.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 反序列化对象
* @return
*/
private Object readObject(){
try {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(new File("D:/object.txt")));
Object object = ois.readObject();
ois.close();
return object;
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
}
package core.java.serializable;
import java.io.Serializable;
/**
* 序列化实体
* @author author
*
*/
public class User implements Serializable{
/**
*
*/
private static final long serialVersionUID = 8511909251520938165L;
private int id;
private String name;
private String sex;
public User(int id, String name, String sex){
super();
this.id = id;
this.name = name;
this.sex = sex;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
}
控制台输出结果:
开始序列化--------------
开始反序列化-------------
1,zhangsan,男
如果实体类没有实现序列化接口程序将抛java.io.NotSerializableException异常
另外在将某个对象序列化的时候实现Serializable接口的时候通常都会添加一个静态
不可改变值的序列化版本号编号,这将是这个序列化对象的唯一标识,如果我们没有
添加,该类会出现警告的信息提示我们添加,但是如果我们不添加系统会默认给该类
指定一个编号,只是我们没看到。但是这样会有一些安全隐患,比如我们将一个对象
持久化到本地,这个时候我们在类中添加一个额外的属性,再进行反序列化的时候将
本地字节序列恢复到对象的时候就会抛java.io.InvalidClassException异常,、
异常信息:core.java.serializable.User; local class incompatible:
stream classdesc serialVersionUID = -9060100527542415407,
local class serialVersionUID = 8511909251520938165
意思就是本地的类和字节序列中的类不是同一个类,因为他们两个类的版本号不一样。
在进行反序列化的时候本地的类是无效的。所以当我们在进行对象序列化的时候一定
要添加上序列化版本号,以防程序抛异常。