1.5.3 序列化单例和类型安全的枚举
对于枚举类型,是符合单例的,但是通过序列化再反序列化创建的对象和已有的对象不是同一个对象。比如枚举类型 Orientation.HORIZONTAL 经过序列化反序列化后,新创建的从流中取出的 Orientation 和 Orientation.HORIZONTAL 不是同一个对象。
此时需要通过 键值直接拿到正确的序列化对象
Main.java
❤🧡💛💚💙💜🤎🖤❤🧡💛💚💙💜🤎🖤❤🧡💛💚💙💜🤎🖤
import com.dyy.jdk8.test.Employee;
import com.dyy.jdk8.test.MyColor;
import java.io.*;
public class Main {
public static Employee[] staff = new Employee[3];
public static void main(String[] args) throws IOException, ClassNotFoundException {
Main solution = new Main();
staff[0] = new Employee("Carl Cracker", 75000,1987, 12, 15);
staff[1] = new Employee("Harry Hacker", 50000, 1989, 10, 1);
staff[2] = new Employee("Tony Tester", 40000, 1990, 3, 15);
for(int i = 0; i < 3; i++){
staff[i].setColor(MyColor.getColorByInt(i+1));
}
ObjectOutputStream oo = new ObjectOutputStream(new FileOutputStream(new File("E:/aa.txt")));
for(Employee clerk:staff){
oo.writeObject(clerk);
}
//反序列化
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(new File("E:/aa.txt")));
Employee[] readStaff = new Employee[3];
for(int i = 0; i < 3; i++){
readStaff[i] = (Employee) ois.readObject();
System.out.println(readStaff[i].getColor()==staff[i].getColor());
}
}
}
❤🧡💛💚💙💜🤎🖤❤🧡💛💚💙💜🤎🖤❤🧡💛💚💙💜🤎🖤
MyColor.java
❤🧡💛💚💙💜🤎🖤❤🧡💛💚💙💜🤎🖤❤🧡💛💚💙💜🤎🖤
public enum MyColor {
BLUE(1),RED(2),YELLOW(3);
private int color;
MyColor(int color){
this.color = color;
}
public int getColor() {
return color;
}
public static MyColor getColorByInt(int val){
switch (val){
case 1: return BLUE;
case 2: return RED;
case 3: return YELLOW;
}
return null;
}
}
❤🧡💛💚💙💜🤎🖤❤🧡💛💚💙💜🤎🖤❤🧡💛💚💙💜🤎🖤
Employee.java
❤🧡💛💚💙💜🤎🖤❤🧡💛💚💙💜🤎🖤❤🧡💛💚💙💜🤎🖤
import java.io.*;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
public class Employee implements Serializable{
private String name;
private double salary;
private Date hireDay;
private MyColor color;
public static final int NAME_SIZE = 40;
public static final int RECORD_SIZE = 2*NAME_SIZE+20;
public Employee(){}
public Employee(String n, double s, int year, int month, int day){
name = n;
salary = s;
GregorianCalendar calendar = new GregorianCalendar(year,month-1, day);
hireDay = calendar.getTime();
}
public MyColor getColor() {
return color;
}
public void setColor(MyColor color) {
this.color = color;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
public Date getHireDay() {
return hireDay;
}
public void setHireDay(Date hireDay) {
this.hireDay = hireDay;
}
public void raiseSalary(double byPercent){
double raise = salary*byPercent/100;
salary+=raise;
}
@Override
public String toString() {
return getClass().getName() + "[name="+name+",salary="+salary+",hireDay="+hireDay+"]";
}
public void writeData(DataOutput out) throws IOException {
DataIO.writeFixedString(name,NAME_SIZE, out);
out.writeDouble(salary);
GregorianCalendar calendar = new GregorianCalendar();
calendar.setTime(hireDay);
out.writeInt(calendar.get(Calendar.YEAR));
out.writeInt(calendar.get(Calendar.MONTH)+1);
out.writeInt(calendar.get(Calendar.DAY_OF_MONTH));
out.writeInt(color.getColor());
}
public void readData(DataInput in) throws IOException {
name = DataIO.readFixedString(NAME_SIZE, in);
salary = in.readDouble();
int y = in.readInt();
int m = in.readInt();
int d = in.readInt();
GregorianCalendar calendar = new GregorianCalendar(y,m-1,d);
hireDay = calendar.getTime();
color = MyColor.getColorByInt(in.readInt());
}
private void writeObject(java.io.ObjectOutputStream out)
throws IOException{
out.writeUTF(name);
out.writeDouble(salary);
out.writeLong(hireDay.getTime());
out.writeInt(color.getColor());
// out.writeObject(color);
}
private void readObject(java.io.ObjectInputStream in)
throws IOException, ClassNotFoundException{
name = in.readUTF();
salary = in.readDouble();
hireDay = new Date(in.readLong());
color = MyColor.getColorByInt(in.readInt());
// color = (MyColor) in.readObject();
}
}
❤🧡💛💚💙💜🤎🖤❤🧡💛💚💙💜🤎🖤❤🧡💛💚💙💜🤎🖤
运行结果:
使用int处理,true
不使用int处理,true
原因:实际进行这个序列化操作是跨主机的,对于不同主机而言,即使是类名、对象内容完全一致也和原机器中数据是不同对象
1.5.4 版本管理
版本:ANY-ACCESS-MODIFIER static final long serialVersionUID = 42L;
在序列化对象中,可使用 serialVersionUID 校验版本。可用于检查类字段的变化,如果发生变化,写入和读出两端的版本不一致时会产生异常
如果不写这个版本,可能因为系统的不同,环境的不同而使得自动生成的 UID 不一致,从而造成无法读出的情况,所以官方推荐我们要写入这个字段。
评论🌹点赞👍收藏✨关注👀,是送给作者最好的礼物,愿我们共同学习,一起进步
公众号 钰娘娘知识汇总