题目取得有点怪异,不管这个,其实是要说一下 java 中的 java.io.Serializable 接口。
首先,先来了解一下什么是 序列化 ( Serializable ) :
对象的寿命通常随着生成该对象的程序块的终止而终止。有时候,你可能需要将对象的状态保存下来,在需要时再将对象恢复(反序列化)。
我们把对象的这种能记录自己的状态以便将来再生的能力,叫做对象的持久性 ( persistence )。
对象通过写出描述自己状态的数值来记录自己,这个过程就叫对象的序列化 ( Serialization ) 。
类可以通过实现 java.io.Serializable 接口来启用其序列化功能。未实现此接口的类将无法使其任何状态序列化或反序列化。
类实现 java.io.Serializable 接口,无需实现任何方法或字段,因为 java.io.Serializable 接口本身就没有方法或字段,它仅用来标识可序列化的语义。
Java 序列化技术可以让你将一个对象的状态写入到一个 IO 流里,并且可以从其它地方把该 IO 流里的数据读出来。重新构造一个相同的对象。
这就有点像你将数据存储到数据库里,然后再拿出来,这前后得到的东西是一样的。它的这种机制允许你将对象通过网络进行传播,
并可以随时把对象持久化到数据库、文件等系统里。
另外,序列化运行时使用一个称为 serialVersionUID 的版本号与每个可序列化类相关联,
该序列号在反序列化过程中用于验证序列化对象的发送者和接收者是否为该对象加载了与序列化兼容的类。
如果接收者加载的该对象的类的 serialVersionUID 与对应的发送者的类的版本号不同,则反序列化将会导致失败并抛出 InvalidClassException。
如还想要更进一步的详细信息,可以自行查看 JDK 的 API,里面对 Serializable 做了比较详细的解释。
接下来做个小示例 :
package net.yeah.fancydeepin.model;
import java.io.Serializable;
public class User implements Serializable{
private static final long serialVersionUID = 1L;
private Integer id;
private String name;
public User(){
}
public User (Integer id, String name){
this.id = id;
this.name = name;
}
public Integer getId() {
return id;
}
public String getName() {
return name;
}
public void setId(Integer id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
}
Junit 测试 :
package junit.test;
import org.junit.Test;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import net.yeah.fancydeepin.model.User;
public class TestApp {
@Test
public void serializable() throws Exception{
User user = new User(9080, "fancy");
ObjectOutputStream outStream = new ObjectOutputStream(new FileOutputStream("user.ser"));
outStream.writeObject(user);
System.out.println("<---- Finished ---->");
}
@Test
public void inverseSerializable() throws Exception{
ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream("user.ser"));
User user = (User)inputStream.readObject();
System.out.println("ID : " + user.getId());
System.out.println("name : " + user.getName());
}
}
选中 serializable 方法,右键,Run As Junit Test,后台输出 :
<---- Finished ---->
选中工程名,按 F5 刷新一下,在项目名的根目录下就生成了一个 user.ser 文件,这就是 User 对象序列化生成的文件,它记录了 User 对象的一些状态信息,
当然,你可以根据需要选择文件的存放路径。
选中 inverseSerializable 方法,右键,Run As Junit Test,后台输出 :
ID : 9080
name : fancy
1 . 若将 User 类中的序列化接口实现去掉 :
package net.yeah.fancydeepin.model;
public class User{
private Integer id;
private String name;
public User(){
}
public User (Integer id, String name){
this.id = id;
this.name = name;
}
public Integer getId() {
return id;
}
public String getName() {
return name;
}
public void setId(Integer id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
}
其余不变,再次运行 Junit Test 的 serializable 方法,后台抛出异常 :
java.io.NotSerializableException: net.yeah.fancydeepin.model.User
2 . 先将 User 类撤销回来 :
package net.yeah.fancydeepin.model;
import java.io.Serializable;
public class User implements Serializable{
private static final long serialVersionUID = 1L;
private Integer id;
private String name;
public User(){
}
public User (Integer id, String name){
this.id = id;
this.name = name;
}
public Integer getId() {
return id;
}
public String getName() {
return name;
}
public void setId(Integer id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
}
其余不变,再次运行 Junit Test 的 serializable 方法,先让它正确序列化 User 对象生成 user.ser,接着,修改 serialVersionUID 的值 :
private static final long serialVersionUID = 10086L;
接着,运行 Junit Test 的 inverseSerializable 方法,后台抛出异常 :
java.io.InvalidClassException: net.yeah.fancydeepin.model.User; local class incompatible: stream classdesc serialVersionUID = 1, local class serialVersionUID = 10086
这两个异常是为了帮助朋友们理解 Serializable,异常信息都比较容易理解和接受,这里就不多解释了,本文也到此结束。