序列化与反序列化
- 序列化: 将对象存储到文件中
- 反序列化: 将对象从文件中反序列化出来的操作
- 使用的过程很简单,但是出现了很多的bug,所以现在很少使用了,java官方团队声明以后会淘汰
package IO.xuliehua;
import java.io.*;
public class Demo {
public static void main(String[] args) throws IOException, ClassNotFoundException {
//序列化与反序列化
/* //序列化
Person P = new Person("吴承恩", 18);
Book b =new Book("西游记", "西天取经的故事", P);
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("c://book.txt"));
oos.writeObject(b);
oos.close();*/
//反序列化
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("c://book.txt"));
//Object o = ois.readObject();
Book o = (Book) ois.readObject();//也可以直接强转
System.out.println(o.getName());
System.out.println(o);//o.toString也是一样的
/*Person P = new Person("吴承恩", 18);
Book b =new Book("西游记", "西天取经的故事", P);
System.out.println(P.toString());
System.out.println(b);*/
}
static class Person implements Serializable {
private String pname;
private int age;
public Person(String pname, int age) {
this.pname = pname;
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"pname='" + pname + '\'' +
", age=" + age +
'}';
}
}
static class Book implements Serializable {
//Serializable需要这个标记,才可以实现序列化,否则抛出异常
private String name;
private String info;
private Person user;//这个Person类的对象也要有Serializable标记
public Book(String name, String info, Person user) {
this.name = name;
this.info = info;
this.user = user;
}
@Override
public String toString() {
return "Book{" +
"name='" + name + '\'' +
", info='" + info + '\'' +
", user=" + user +
'}';
}
public Book() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getInfo() {
return info;
}
public void setInfo(String info) {
this.info = info;
}
public Person getUser() {
return user;
}
public void setUser(Person user) {
this.user = user;
}
}
}
1、Serializable实现序列化和反序列化
- 对象实体类
import java.io.Serializable;
import java.util.List;
public class Student implements Serializable {
private String num;
private String name;
private List<String> teacherList;
public Student() {
}
public Student(String num, String name, List<String> teacherList) {
this.num = num;
this.name = name;
this.teacherList = teacherList;
}
@Override
public String toString() {
return "Student{" +
"num='" + num + '\'' +
", name='" + name + '\'' +
", teacherList=" + teacherList +
'}';
}
public String getNum() {
return num;
}
public void setNum(String num) {
this.num = num;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<String> getTeacherList() {
return teacherList;
}
public void setTeacherList(List<String> teacherList) {
this.teacherList = teacherList;
}
}
- 操作类
import java.io.*;
public class MySerializableUtil {
/**
* 将对象序列化到指定的文件中
* @param obj
* @param filename
*/
public static void mySerializableUtil(Object obj, String filename) throws IOException {
OutputStream out = new FileOutputStream(filename);
ObjectOutputStream oos = new ObjectOutputStream(out);
oos.writeObject(obj);
oos.close();
}
//对象的反序列化
/**
* 从指定的文件中反序列化对象
* @param filename
* @return
*/
public static Object myDesSerializable(String filename) throws IOException, ClassNotFoundException {
InputStream is = new FileInputStream(filename);
ObjectInputStream ois = new ObjectInputStream(is);
Object obj = ois.readObject();
return obj;
}
}
- 主函数类
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class MainTest {
public static void main(String[] args) {
List<String> teacherList = new ArrayList<>();
teacherList.add("空空道人");
teacherList.add("贾代儒");
Student stu1 = new Student("1001", "贾宝玉", teacherList);
System.out.println("原始对象: " + stu1);
//对象的序列化
String filename = "stu1.txt";
try {
//序列化
MySerializableUtil.mySerializableUtil(stu1, filename);
System.out.println("序列化对象完成");
//反序列化
Object obj = MySerializableUtil.myDesSerializable(filename);
if(obj instanceof Student) {//obj是student 的父类关系
Student student = (Student) obj;
System.out.println("反序列化后的对象 :" + student);
}
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
//反序列化
}
}
2、部分属性的序列化
实现部分字段序列化的方式:
- 使用transient修饰符(加了的属性就会取消序列化)
- 使用static修饰符
- 默认方法writeObject和readObject
方法1: transient
- 加了transient修饰符的不参与序列化
public class Student implements Serializable {
private String num;
private transient String name;//加了transient,对象序列化过程中不会被序列化了
private transient List<String> teacherList;
}
方法2: static
- 变量加上static修饰符
- 序列化完成后修改名字
查看运行结果:
很明显,我么修改名字实在序列化完成后执行的,所以我们不可能修改文件里面的序列化内容,所以只能是加了static 修饰符的属性没有参加序列化
方法3:writeObject 和 readObject
- 添加的方法必须是
private void ....
- Serializable接口中查看
public class Student implements Serializable {
private String num;
private String name;
private List<String> teacherList;
private void writeObject(java.io.ObjectOutputStream out) throws IOException {
out.writeObject(num);//只对这两个属性进行了序列化
out.writeObject(name);
}
private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
num = (String)in.readObject();
name = (String)in.readObject();
}
······················
执行结果:
3、Externalizable实现java序列化
- Externalizable继承自Serializable接口,使用Externalize就是需要实现readExternal方法和writeExternal方法中实现序列化和反序列化
//在Students实体类中实现两个方法
@Override
public void writeExternal(ObjectOutput out) throws IOException {
out.writeObject(num);
out.writeObject(name);
out.writeObject(teacherList);
}
@Override
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
num = (String)in.readObject();
name = (String)in.readObject();
teacherList = (List<String>)in.readObject();
}
Serializable与Externalizable的比较
写于2021-08-06