目录
一、序列化和反序列化的理解
序列化(Serialize):把java对象存储到文件中,保存java对象的状态的过程;
反序列化(DeSerialize):将硬盘上的保存的java对象重新恢复到内存中,回复成java对象;
二、序列化和反序列化的实现
1、写一个类:
import java.io.Serializable;
/**
* 准备序列化的类要实现Serializable接口
*/
public class User implements Serializable {
//用户ID
private int id;
//用户名称
private String name;
//无参构造
public User() {
}
//有参构造
public User(int id, String name) {
this.id = id;
this.name = name;
}
//重写toString方法
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
2、序列化
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
/**
* 序列化
*/
public class Test {
public static void main(String[] args) {
//创建java对象
User user=new User(123,"zhangsan");
//序列化
ObjectOutputStream oos=null;
try {
//Users是序列化之后的文件名字
oos=new ObjectOutputStream(new FileOutputStream("Users"));
//序列化对象
oos.writeObject(user);
//刷新
oos.flush();
} catch (IOException e) {
e.printStackTrace();
}finally {
//关闭
try {
oos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
序列化对象后会产生一个文件(位置在项目的根目录下):
3、反序列化
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
/**
* 反序列化
*/
public class Test01 {
public static void main(String[] args) {
ObjectInputStream ois=null;
//反序列化
try {
//这个Users是文件的名称(位置在项目根路径下)
ois=new ObjectInputStream(new FileInputStream("Users"));
//读
Object obj=ois.readObject();
//输出
System.out.println(obj);
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}finally {
//关闭
try {
ois.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
反序列化结果:
4、一次序列化多个对象
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.List;
/**
* 序列化
*/
public class Test {
public static void main(String[] args) {
//创建集合
List<User> users=new ArrayList<>();
//创建对象添加到集合中
users.add(new User(123,"zahngsna"));
users.add(new User(456,"lisi"));
users.add(new User(789,"wangwu"));
//序列化
ObjectOutputStream oos=null;
try {
oos=new ObjectOutputStream(new FileOutputStream("Users"));
//序列化对象集合
oos.writeObject(users);
//刷新
oos.flush();
} catch (IOException e) {
e.printStackTrace();
}finally {
//关闭
try {
oos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
反序列化后的结果:
三、transient关键字
transient关键字表示游离的,被transient修饰的关键字不能被序列化
例如
import java.io.Serializable;
/**
* 准备序列化的类要实现Serializable接口
*/
public class User implements Serializable {
//用户ID
private int id;
//用transient修饰用户名称
private transient String name;
//无参构造
public User() {
}
//有参构造
public User(int id, String name) {
this.id = id;
this.name = name;
}
//重写toString方法
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
序列化然后再反序列化的结果为:
四、关于序列化版本号
1、概述
java虚拟机在看到Serializable接口之后,就会自动生成一个序列化版本号
在一个项目中,若是有两个名字相同的类,JVM就会通过这两个类的序列化版本号来进行区分
如果是同一个类,后期做了修改,重新编译,也会重新生成一个序列化版本号,jvm还是会认为是一个全新的类;
为了防止这样,可以自定义序列化版本号
建议只要实现了Serializable接口的类,都手动指定序列化版本号,这样后期修改代码,序列化版本号不变,JVM会认为是同一个类;
2、手动定义序列化版本号
private static final long serialVersionUID = 1232L;