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是从文件中还原类的对象 也不会调用构造函数
1.使用new关键字 2.使用clone方法 3.反射机制 4.反序列化
其中1,3都会明确的显式的调用构造函数
2是在内存上对已有对象的影印 所以不会调用构造函数
4是从文件中还原类的对象 也不会调用构造函数
上述代码就是反序列化的结果
RednaxelaFX 写道
嗯顺带推荐Effective Java, Second Edition的第74条
引用
Normally, objects are created using constructors;
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.
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.
大体的意思是反序列化有一定的风险.破坏了封装.相当于一个隐藏的构造器.
RednaxelaFX 写道
1、Java的实例构造器只负责初始化,不负责创建对象;Java虚拟机的字节码指令的设计也反映了这一点,有一个new指令专门用于创建对象实例,而调用实例构造器则使用invokespecial指令。
2、“this”是作为实例构造器的第一个实际参数传入的。
2、“this”是作为实例构造器的第一个实际参数传入的。
Java反序列化实际上是调用了基类的构造方法.
ObjectStreamClass中调用ReflectionFactory.newConstructorForSerialization(cl, cons);
- cons = reflFactory.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
public java.lang.Object() TestClass@fd13b5
通过基类的方法调用生成了子类.绕开了TestClass类的构造方法.生成了看似不可能存在的TestClass对象
-----------------------------------------------------------------------------------
感谢FX,之前一篇关于构造器的详细论述.传送门 http://rednaxelafx.iteye.com/blog/652719
FX写的关于本篇的更详细讲解在这里,传送门 http://rednaxelafx.iteye.com/blog/850082