序列化的意义
序列化机制将Java对象转换为字节序列,这些字节序列可以保存在磁盘上,或通过网络传输。序列化机制使得java对象可以脱离程序而独立存在。
Java讲究万物皆对象,信息大多数都存储在对象内部(属性),所以需要保存对象至关重要。然而保存对象的前提是对象已经进行了序列化。
使用场景
- 把对象进行网络传输
- 把对象保存到磁盘
- 数据缓存
可序列化的类
- 如果父类是可序列化的,那么子类可以序列化
- 如果类的全部成员是可序列化的,那么类可以序列化
序列化和反序列化的Demo
Person类
//Student继承Serializable,可以进行序列化
public class Student implements Serializable {
//无参构造函数
public Student() {
}
//有参构造函数
public Student(String name) {
this.name = name;
}
/*
name是Student的成员变量,name的类型是String(可序列化),所以Student可以正常序列化。
*/
private String name;
//get
public String getName() {
return name;
}
//set
public void setName(String name) {
this.name = name;
}
//重写equlas
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return name.equals(student.name);
}
//重写hashcode
@Override
public int hashCode() {
return Objects.hash(name);
}
//重写tostring
@Override
public String toString() {
return "student{" +
"name='" + name + '\'' +
'}';
}
}
主函数
/*
1、参数
file是文件对象
object是写入的对象
2、主要功能
把对象序列化后写入文件,规则:一个文件只写一个对象
*/
public static void writer(File file, Object object) {
//文件不存在就创建文件
if (!file.exists()) {
try {
//创建文件
file.createNewFile();
System.out.println("文件不存在,创建文件成功...");
} catch (IOException e) {
e.printStackTrace();
}
}
System.out.println("开始写文件...");
try {
//实例化FileOutputStream对象
FileOutputStream fileOutputStream = new FileOutputStream(file);
//实例化objectOutputStream对象
ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
//把对象写入文件
objectOutputStream.writeObject(object);
//关闭流
objectOutputStream.close();
fileOutputStream.close();
System.out.println("写入结束,关闭流成功...");
} catch (IOException e) {
System.out.println("写入失败!");
e.printStackTrace();
}
}
/*
1、参数
file是文件对象
2、主要功能
把序列化后的文件转换为对象
3、返回值
一个Object类的对象
*/
public static Object reader(File file) {
//如果文件不存在退出程序
if (!file.exists()) {
System.out.println("读取的文件不存在!");
//退出程序
System.exit(1);
}
System.out.println("开始读文件...");
try {
//实例化FileInputStream对象
FileInputStream fileInputStream = new FileInputStream(file);
//实例化ObjectInputStream对象
ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);
//读取对象
Object object = null;
try {
object = objectInputStream.readObject();
} catch (ClassNotFoundException e) {
System.out.println("读取失败!");
e.printStackTrace();
}
//关闭连接
objectInputStream.close();
fileInputStream.close();
System.out.println("读取结束,关闭流成功...");
//返回读取的对象
return object;
} catch (IOException e) {
System.out.println("读取失败!");
e.printStackTrace();
}
//发生异常返回null
return null;
}
public static void main(String[] args) {
//实例化多个对象
Student a = new Student("小红");
Student b = new Student("小蓝");
Student c = new Student("小黄");
//定义集合
List<Student> list = new ArrayList<>();
//把对象加入集合
list.add(a);
list.add(b);
list.add(c);
//文件路径
String filePath = "object.txt";
//实例化File对象
File file = new File(filePath);
//把集合对象序列化后写入文件
writer(file, list);
//把文件进行反序列化转为对象
Object reader = reader(file);
//把对象进行强制转换,因为返回的是Object类
List<Student> students = (List<Student>) reader;
//遍历输出对象
for (Student student : students) {
System.out.println(student);
}
}
总结
- 反序列化不会调用构造方法(感觉这个结论有点傻)
- 一个对象不会被多次序列化
比如:你把对象A序列化后写入文件,然后又一次把对象A序列化写入文件,这时,系统发现A已经存在于文件中,只会写入A的编号(指针的感觉)。
带来的bug:如果A先写入文件,然后A属性值发生了改变,这时想更新文件中的A,再把A写入文件,系统保存的是修改前的属性值(A第一次存入文件的属性)。