不用构造器也能创建对象

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
CSDN某帖子 写道
对象创建的几种方法:
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.

大体的意思是反序列化有一定的风险.破坏了封装.相当于一个隐藏的构造器.
RednaxelaFX 写道
1、Java的实例构造器只负责初始化,不负责创建对象;Java虚拟机的字节码指令的设计也反映了这一点,有一个new指令专门用于创建对象实例,而调用实例构造器则使用invokespecial指令。
2、“this”是作为实例构造器的第一个实际参数传入的。

Java反序列化实际上是调用了基类的构造方法.
ObjectStreamClass中调用ReflectionFactory.newConstructorForSerialization(cl, cons);
Objectstreamclass代码 复制代码 收藏代码
  1. cons = reflFactory.newConstructorForSerialization(cl, cons);  

根据cl参数(TestClass类的Class对象)和cons参数(基类Object的构造器)创建了一个新的构造器
打印生成的构造器对象,输出信息为public java.lang.Object(),表面生成的构造器是TestClass父类Object的无参构造器.
但是调用newInstance()的结果却产生了TestClass类的对象.(おかしい......)

ReflectionFactory.newConstructorForSerialization()例子
Java代码 复制代码 收藏代码
  1. Constructor superCons = TestClass.class.getSuperclass().getConstructor();   
  2. System.out.println(superCons);   
  3. ReflectionFactory reflFactory = ReflectionFactory.getReflectionFactory();   
  4. Constructor c = reflFactory.newConstructorForSerialization(TestClass.class,superCons);   
  5. 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());

运行结果代码 复制代码 收藏代码
  1. public java.lang.Object()   
  2. TestClass@fd13b5  

通过基类的方法调用生成了子类.绕开了TestClass类的构造方法.生成了看似不可能存在的TestClass对象

-----------------------------------------------------------------------------------
感谢FX,之前一篇关于构造器的详细论述.传送门http://rednaxelafx.iteye.com/blog/652719
FX写的关于本篇的更详细讲解在这里,传送门http://rednaxelafx.iteye.com/blog/850082

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章