1. 什么是序列化:
a) 把对象转换为字节序列的过程叫序列化对象。
b) 把字节序列恢复为对象的过程叫反序列化。
2.用途:【序列化之后就可以存储在内存中或在网络中传输】
3、序列化的实现方式:2种
a) 实现 Serializable 接口:java.io.ObjectOutputStream表示对象输出流,writeObject(obj)把指定对象序列化把得到的字节序列写到目标输出流;序列化的时候的一个关键字:transient(临时的)。它声明的变量实行序列化操作的时候不会写入到序列化文件中去。
b) 实现 Externalizable 接口(很少使用)::java.io.ObjectInputStream表示对象输出流,readObject(obj)将其反序列化并得到对象; 一个类中我们只希望序列化一部分数据,其他数据都使用transient修饰的话显得有点麻烦,这时候我们使用externalizable接口,指定序列化的属性。
4. Java中常见的序列化: 包括Java原生以流的方法进行的序列化、Json序列化、FastJson序列化、Protobuff序列化。
https://blog.csdn.net/pistolove/article/details/60321123
5. 解释SerialVersionUID的两种方式:
a) default: 1L
b) 根据报名类名方法名变量名来产生一个64bit的hash字段。
作用:如果不写SerialVersionUID的话,java编译器会进行摘要,有一丝的变化摘要都是不同,安全机制都会拒绝加载,而如果显示写出只要UID相同就不会拒绝加载。
6.注意:
a) 父类实现序列化,子类自动序列化,无需显示实现。
b) 当一个对象的实例变量引用其他对象时,序列化该对象也要序列化引用对象。
c) 并不是所有的对象都是可以序列化的。
d) 尽量不要使用,可能存在 bug 和 security 问题;增加了 Test 的压力。
e) 要被继承的类和接口尽量不要序列化。
f) 即使要是有序列化,也要尽量使用自定义序列化(自定义readObject和writeObject)。
Example:
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.Serializable;
import java.util.Date;
public class Period implements Serializable {
private final Date start;
private final Date end;
public Period(Date start, Date end) {
this.start = new Date(start.getTime());
this.end = new Date(end.getTime());
if (this.start.compareTo(this.end) > 0)
{
throw new IllegalArgumentException(
this.start + " is after " + this.end);
}
}
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
in.defaultReadObject();
// Check that our invariants are satisfied
if (this.start.compareTo(this.end) > 0)
{
throw new IllegalArgumentException(
this.start + " is after " + this.end);
}
}
public Date start() {
return start;
}
public Date end() {
return end;
}
public static void main(String[] args) {
Date date1 = new Date(1225481126447L);
Date date2 = new Date(1403441275025L);
Period period = new Period(date1, date2);
System.out.println(period.start());
date1.setTime(1325481126447L);
System.out.println(period.start());
}
}
Example2:
package serialization; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.ObjectStreamException; import java.io.Serializable; public class SerializeTest implements Serializable { private static final long serialVersionUID = -7066215824837902304L; private String message = null; private int number = 0; private Object writeReplace() throws ObjectStreamException { System.out.println("writeReplace invoked"); return this; } private void writeObject(ObjectOutputStream out) throws IOException { System.out.println("writeObject invoked"); out.writeObject(this.message == null ? "------" : this.message); } private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { System.out.println("readObject invoked"); this.message = (String) in.readObject(); System.out.println("get message:" + this.message); } private Object readResolve() throws ObjectStreamException { System.out.println("readResolve invoked"); return this; } public Object serialize() throws IOException, ClassNotFoundException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(baos); oos.writeObject(this); ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); ObjectInputStream ois = new ObjectInputStream(bais); return ois.readObject(); } public static void main(String[] args) throws IOException, ClassNotFoundException { SerializeTest foo = new SerializeTest(); foo.serialize(); } }