1、序列化是什么?
序列化是一种处理对象流的机制,所谓对象流就是将对象的内容进行流化。可以对流化的对象进行读写操作,也可以将流化的对象传输于网络之间。序列化是为了解决在对象流进行读写操作是所引发的问题。
把内存里面的这些对象给变成一连串的字节描述的过程。如: 文件保存
2、 序列化的实现以及反序列化
将需要被序列化的类实现Serializable接口,该接口没有需要重写的方法。
implements Serializable
implements Serializable 只是为了标注该对象是可被序列化的,然后使用一个输出流来构造一个ObjectOutputStream(对象流),接着,ObjectOutputStream对象的writeObject(Object obj)方法就可以将参数为obj的对象写出(即保存期状态),使用输入流ObjectInputStream对象的方法readObject() 从一个源输入流中读取字节序列,再把它们反序列化为一个对象,并将其返回。<——输入流进行原对象恢复!
注意:1、静态变量不会被序列化的,它可不在堆内存中,序列化只会序列化堆内存的数据
2、transient 修饰的属性,是不会被序列化的
序列化时最好是定义序列化版本id 即 public static final Long seriaVersionUID = 1L (默认) 或者 xxxxx L(自定义64位都行)
3、自动生成serialVersionUID
3.1 IDEA设置
3.1.1 快捷键:Ctrl+Shift+S 进入设置
3.1.2 步骤ABCD;
3.1.3 步骤C 搜索:serialVersionUID
3.2 光标移到类文件的类名上(类必须实现Serializable接口),按快捷键Alt + Enter 出现 Add 'serialVersionUID' Field
4、序列化
/**
* @Author: Be.insighted
* Description:
* @date Create on 2020/8/12 16:40
**/
public class Person implements Serializable {
private static final long serialVersionUID = 1L;
private static String sex = "男";
private int age;
private String name;
transient private String adress;
public static String getSex() {
return sex;
}
public static void setSex(String sex) {
Person.sex = sex;
}
public String getAdress() {
return adress;
}
public void setAdress(String adress) {
this.adress = adress;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Person{" +
"age=" + age +
", name='" + name + '\'' +
", adress='" + adress + '\'' +
", sex=" + sex +
'}';
}
}
序列化并反序列化:
/**
* @Author: Be.insighted
* Description:
* @date Create on 2020/8/12 16:45
**/
public class TestSerializable {
public static void main(String[] args) throws Exception{
serialized();
Person person = deSerialized();
System.out.println("反序列化: " + person);
}
private static void serialized() throws IOException{
Person person = new Person();
person.setAdress("济源市");
person.setAge(18);
person.setName("特朗普");
System.out.println("序列化: " + person);
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(new File("d:/person.txt")));
oos.writeObject(person);
System.out.println("对象序列化成功!");
oos.close();
}
private static Person deSerialized() throws Exception{
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(new File("d:/person.txt")));
Person person = (Person)ois.readObject();
System.out.println("字节流反序列化成功!");
ois.close();
return person;
}
}
结果:
生成文件:
代码仅注释掉 // erialized(); 以及 将person的 sex = "女"; 运行,看输出:
竟然:sex = 女 !!! 说明,类变量不会被序列化!!!
5、反序列化:
transient修饰的属性没有被序列化,反序列化的时候无值 <------- adress的值 'null'
NotSerializableException <------ 解决: 请给对应的类实现序列化
如果没有显示的声明 serialVersionUID 的值,Java会自动的给我赋值的,这个值跟这个对象的属性相关计算出来的。
6、实现这个Serializable 接口的时候,一定要给这个 serialVersionUID 赋值
“serialVersionUID” 的字段(该字段必须是静态 (static)、最终 (final) 的 long 型字段)显式声明其自己的 serialVersionUID。
没写这个 serialVersionUID ,扩展的时候可能就会出现不认识旧数据的bug!!!
7、不是Java编译器会自动生成么?那为什么还要显示声明呢?
为了避免在到处运行时出现不一致问题,保证 serialVersionUID 值跨不同 java 编译器实现的一致性,序列化类必须声明一个明确的 serialVersionUID 值。
8、子类实现序列化,父类没有实现,子类可以实现序列化么?
如果父类没有声明无参构造函数,实现序列化失败!
9、类中存在引用对象,那么这个类在什么情况下能够序列化?
类中的所有属性都必须是可以序列化的,这个类才能序列化。
10、同一个对象多次序列化(中间有属性更新),会影响序列化么?
同一个对象多次序列化,Java8不会为这个对象进行多次序列化。序列化会有一个独一无二的编码号,再次序列化的时候校验到该编码号则不会再序列化!