Java 反序列化是如何工作的?

Java 反序列化是如何工作的?,java,serialization,deserialization,Java,Serialization,Deserialization,据我所知,对象被序列化的类的构造函数并没有被调用,而是第一个不可序列化构造函数的无参数构造函数。现在考虑下面的代码 public class SerializeDemo implements Serializable { private String name; int age; //default 0 public SerializeDemo(String name, boolean setAge){ this.name = name; if(setAge){

据我所知,对象被序列化的类的构造函数并没有被调用,而是第一个不可序列化构造函数的无参数构造函数。现在考虑下面的代码

public class SerializeDemo implements Serializable {

private String name;
int age;    //default 0

public SerializeDemo(String name, boolean setAge){
    this.name = name;
    if(setAge){
        this.age = 18;
    }
}

@Override
public String toString() {
    return "Name is " + name + " and age is " + age;
}

public static void main(String args[]) throws IOException, ClassNotFoundException {

    ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(new File("//home//aniket//Desktop//serializedObjects.txt")));
    ObjectInputStream ois = new ObjectInputStream(new FileInputStream(new File("//home//aniket//Desktop//serializedObjects.txt")));
    SerializeDemo sd = new SerializeDemo("Test",true);
    System.out.println("Before Serialization : " + sd);
    oos.writeObject(sd);
    SerializeDemo sdCopy = (SerializeDemo)ois.readObject();
    System.out.println("After Deserialization : " + sdCopy);
}
}
并且输出是(如预期的那样)

现在,没有参数构造函数的不可序列化的超类是Object(如果我错了,请纠正我)。所以基本上不调用序列化的demo构造函数

现在,当在反序列化过程中创建对象时,它将尝试重建实例状态。因此,它将年龄设定为18岁

问题是怎么做

我故意不提供二传手。也不是根据上面的讨论,它的构造函数被调用。那么它是如何设置的呢?(名称也是如此)

现在,没有参数构造函数的不可序列化的超类是Object

所以基本上不调用序列化的demo构造函数

现在,当在反序列化过程中创建对象时,它将尝试重建实例状态。因此,它将年龄设定为18岁

问题是怎么做

反射。。。在访问检查关闭的情况下

序列化类中的类描述符提供所有序列化字段的名称和类型。
对象定义实际类的
字段
对象。反序列化代码将可用的序列化字段与
字段
对象匹配,然后使用
字段.set(…)
方法设置字段值


(事实上,这是一个实现细节,但这是我对它在当前一代JVM中如何工作的理解。您可以随时查看源代码…

您可以查看
ObjectInputStream
源代码。它使用反射,创建对象,从流中读取字段,并使用反射设置对象的字段。您可以在调试器中运行代码,一步一步地精确到设置年龄的行。

它在ObjectInputStream这样的情况下有效吗?正如我所知,您必须在实现可序列化接口的类中提供非参数构造函数,但当缺少非参数构造函数时,有些类(如ObjectInputStream)在反序列化中不会成为truble。我说的对吗?如果类实现可序列化ObjectInputStream忽略其构造函数,它将创建一个统一化的对象并在其中注入字段是的,我理解这一部分,但如果您通过RMI将对象发送到另一台机器,我知道您必须在其中提供无参数构造函数。RMI以通常的方式使用序列化,空构造函数仅用于Externalizableobjects@biti不,你从哪儿弄来的?RMI封送处理和对象序列化并没有什么不同。您刚才说的对象实例是用从流中获取的值创建和注入的。但是对于我试图序列化的实际类对象的实例,谁将为它创建实例呢?此外,为什么字段值被注入到对象实例中,因为这些不是对象实例的属性,而是与子类中的一个相关。请解释一下!!有一种
不安全的
方法用于执行此操作。阅读源代码。
Before Serialization : Name is Test and age is 18
After Deserialization : Name is Test and age is 18