在Java中实现对象反序列化非常简单,实现java.io.Serializable(内部序列化)
或java.io.Externalizable(外部序列化)
接口即可被序列化,其中java.io.Externalizable
接口只是实现了java.io.Serializable
接口。
反序列化类对象时有如下限制:
- 被反序列化的类必须存在。
serialVersionUID
值必须一致。
除此之外,反序列化类对象是不会调用该类构造方法的,因为在反序列化创建类实例时使用了sun.reflect.ReflectionFactory.newConstructorForSerialization
创建了一个反序列化专用的Constructor(反射构造方法对象)
,使用这个特殊的Constructor
可以绕过构造方法创建类实例(前面章节讲sun.misc.Unsafe
的时候我们提到了使用allocateInstance
方法也可以实现绕过构造方法创建类实例)。
使用反序列化方式创建类实例代码片段:
package com.anbai.sec.serializes;
import sun.reflect.ReflectionFactory;
import java.lang.reflect.Constructor;
/**
* 使用反序列化方式在不调用类构造方法的情况下创建类实例
* Creator: yz
* Date: 2019/12/20
*/
public class ReflectionFactoryTest {
public static void main(String[] args) {
try {
// 获取sun.reflect.ReflectionFactory对象
ReflectionFactory factory = ReflectionFactory.getReflectionFactory();
// 使用反序列化方式获取DeserializationTest类的构造方法
Constructor constructor = factory.newConstructorForSerialization(
DeserializationTest.class, Object.class.getConstructor()
);
// 实例化DeserializationTest对象
System.out.println(constructor.newInstance());
} catch (Exception e) {
e.printStackTrace();
}
}
}
程序运行结果:
com.anbai.sec.serializes.DeserializationTest@2b650cea
具体细节可参考 不用构造方法也能创建对象。