import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.Serializable;
public class TestClass implements Serializable{
private static final long serialVersionUID = 0L;
public TestClass() throws Exception {
throw new Exception("哎呀妈呀,异常啦!!!!");
}
public static void main(String[] args) throws Exception {
byte[] head = { -84, -19, 0, 5, 115, 114, 0 };
byte[] ass = { 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 120, 112 };
String name = TestClass.class.getName();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
baos.write(head);
baos.write(name.length());
baos.write(name.getBytes());
baos.write(ass);
baos.flush();
baos.close();
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray()));
TestClass o = (TestClass) ois.readObject();
ois.close();
System.out.println("创建对象: " + o);
}
}
看到这里先别着急执行,先看看.你觉得能够正常运行吗? 结果是什么? -----------------------------------------------------------------------------------
运行结果: 创建对象: TestClass@743399
1.使用new关键字 2.使用clone方法 3.反射机制 4.反序列化
其中1,3都会明确的显式的调用构造函数
2是在内存上对已有对象的影印 所以不会调用构造函数
4是从文件中还原类的对象 也不会调用构造函数
上述代码就是反序列化的结果
serialization is an extralinguistic mechanism for creating objects. Whether
you accept the default behavior or override it, deserialization is a “hidden constructor”
with all of the same issues as other constructors.
大体的意思是反序列化有一定的风险.破坏了封装.相当于一个隐藏的构造器.
2、“this”是作为实例构造器的第一个实际参数传入的。
Java反序列化实际上是调用了基类的构造方法.
ObjectStreamClass中调用ReflectionFactory.newConstructorForSerialization(cl, cons);
- cons = reflFactory.newConstructorForSerialization(cl, cons);
根据cl参数(TestClass类的Class对象)和cons参数(基类Object的构造器)创建了一个新的构造器
打印生成的构造器对象,输出信息为public java.lang.Object(),表面生成的构造器是TestClass父类Object的无参构造器.
但是调用newInstance()的结果却产生了TestClass类的对象.(おかしい......)
ReflectionFactory.newConstructorForSerialization()例子
- Constructor superCons = TestClass.class.getSuperclass().getConstructor();
- System.out.println(superCons);
- ReflectionFactory reflFactory = ReflectionFactory.getReflectionFactory();
- Constructor c = reflFactory.newConstructorForSerialization(TestClass.class,superCons);
- System.out.println(c.newInstance());
Constructor superCons = TestClass.class.getSuperclass().getConstructor();
System.out.println(superCons);
ReflectionFactory reflFactory = ReflectionFactory.getReflectionFactory();
Constructor c = reflFactory.newConstructorForSerialization(TestClass.class,superCons);
System.out.println(c.newInstance());
- public java.lang.Object()
- TestClass@fd13b5
通过基类的方法调用生成了子类.绕开了TestClass类的构造方法.生成了看似不可能存在的TestClass对象
-----------------------------------------------------------------------------------
感谢FX,之前一篇关于构造器的详细论述.传送门http://rednaxelafx.iteye.com/blog/652719
FX写的关于本篇的更详细讲解在这里,传送门http://rednaxelafx.iteye.com/blog/850082