前言:在Java中实现对象反序列化非常简单,实现java.io.Serializable(内部序列化)或java.io.Externalizable(外部序列化)接口即可被序列化,其中java.io.Externalizable接口只是实现了java.io.Serializable接口
1:序列化对象和反序列化对象(两种方式)
(1)使用java.io.Serializable进行序列化
1:将类实现Serializable这个接口
2:设置serialVersionUID值
3:使用ObjectOutputStream进行序列化
4:使用ObjectInputStream进行反序列化
Text类:
public class Text1 implements Serializable {
@Serial
private static final long serialVersionUID = 3842394723984792L;
public String text="111";
public int number;
public Text1(){
}
public void text1(){
System.out.println("我是text1中的方法");
}
@Override
public String toString() {
return "Text1{" +
"text='" + text + '\'' +
", number=" + number +
'}';
}
}
Main类:
//先字节流建立连接
FileOutputStream out = new FileOutputStream("1.txt");
//转换成序列化流
ObjectOutputStream oos = new ObjectOutputStream(out);
//写入对象
oos.writeObject(new Text1());
//关流
oos.close();
//先字节流建立连接
FileInputStream fis = new FileInputStream("1.txt");
//转换成序列化流
ObjectInputStream ois = new ObjectInputStream(fis);
//读取对象
Text1 o = (Text1)ois.readObject();
//关流
ois.close();
//打印对象
System.out.println(o);
(2)使用java.io.Externalizable进行序列化
1:将类实现Serializable这个接口
2:重写里面的两个方法
3:设置serialVersionUID值
4:使用ObjectOutputStream进行序列化
5:使用ObjectInputStream进行反序列化
Text类:
public class Text1 implements Externalizable {
@Serial
private static final long serialVersionUID = 3842394723984792L;
public String name="张三";
public int number=888888;
public Text1(){
}
public void text1(){
System.out.println("我是text1中的方法");
}
@Override
public String toString() {
return "Text1{" +
"name='" + name + '\'' +
", number=" + number +
'}';
}
@Override
public void writeExternal(ObjectOutput out) throws IOException {
out.writeObject(name);
out.writeInt(number);
}
@Override
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
name = (String) in.readObject();
number = in.readInt();
}
}
Main类:
//先字节流建立连接
FileOutputStream out = new FileOutputStream("1.txt");
//转换成序列化流
ObjectOutputStream oos = new ObjectOutputStream(out);
//写入对象
oos.writeObject(new Text1());
//关流
oos.close();
//先字节流建立连接
FileInputStream fis = new FileInputStream("1.txt");
//转换成序列化流
ObjectInputStream ois = new ObjectInputStream(fis);
//读取对象
Text1 o = (Text1)ois.readObject();
//关流
ois.close();
//打印对象
System.out.println(o);
2:自定义序列化(writeObject)和反序列化(readObject)
当我们对DeserializationTest类进行序列化操作时,会自动调用(反射调用)该类的writeObject(ObjectOutputStream oos)方法,对其进行反序列化操作时也会自动调用该类的readObject(ObjectInputStream)方法,也就是说我们可以通过在待序列化或反序列化的类中定义readObject和writeObject方法,来实现自定义的序列化和反序列化操作,当然前提是,被序列化的类必须有此方法,并且方法的修饰符必须是private,如果该类没有重写,默认调用默认的序列化方法
自定义序列化的使用场景:
1:需要手动处理使用transient关键字不能自动序列化字段
2:字段需要加密后序列化
3:还用更复杂的一些场景
Text类:
public class Text1 implements Serializable {
@Serial
private static final long serialVersionUID = 3842394723984792L;
transient public String name="张三";
public int number=888888;
public Text1(){
}
private void writeObject(ObjectOutputStream out) throws IOException {
out.defaultWriteObject();
out.writeObject(name);
}
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
in.defaultReadObject();
name = (String) in.readObject();
}
@Override
public String toString() {
return "Text1{" +
"name='" + name + '\'' +
", number=" + number +
'}';
}
}
Main类:
//先字节流建立连接
FileOutputStream out = new FileOutputStream("1.txt");
//转换成序列化流
ObjectOutputStream oos = new ObjectOutputStream(out);
//写入对象
oos.writeObject(new Text1());
//关流
oos.close();
//先字节流建立连接
FileInputStream fis = new FileInputStream("1.txt");
//转换成序列化流
ObjectInputStream ois = new ObjectInputStream(fis);
//读取对象
Text1 o = (Text1)ois.readObject();
//关流
ois.close();
//打印对象
System.out.println(o);
3:使用反序列化绕过构造方法创建对象
除此之外,反序列化类对象是不会调用该类构造方法的,因为在反序列化创建类实例时使用了sun.reflect.ReflectionFactory.newConstructorForSerialization创建了一个反序列化专用的Constructor(反射构造方法对象),使用这个特殊的Constructor可以绕过构造方法创建类实例(前面章节讲sun.misc.Unsafe 的时候我们提到了使用allocateInstance方法也可以实现绕过构造方法创建类实例)
步骤:
1:获取sun.reflect.ReflectionFactory对象
2:使用反序列化方式获取某类的构造方法
3:实例化某类的对象
// 获取sun.reflect.ReflectionFactory对象
ReflectionFactory reflectionFactory = ReflectionFactory.getReflectionFactory();
// 使用反序列化方式获取Text1类的构造方法
Constructor<?> constructor = reflectionFactory.newConstructorForSerialization(Text1.class, Object.class.getConstructor());
//实例化Text1的对象
Text1 o = (Text1)constructor.newInstance();
System.out.println(o);