【问题标题】:Internals of java Serialization : Which class initiates Serialization process? [duplicate]java序列化的内部:哪个类启动序列化过程? [复制]
【发布时间】:2016-03-19 02:51:51
【问题描述】:

如果我想序列化一个java对象,我只需要实现标记接口Serializable,它没有任何方法。

class Employee implements Serializable{
    private int id;
    private String name;

    /*
    private void writeObject(ObjectOutputStream out) throws IOException{
        System.out.println("in write object");
    }
    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException{
        System.out.println("in read object");
    }
    */

}

我的查询(编辑):

  1. 通过在我的代码中实现标记接口Serializable,Java 正在序列化我的对象。哪个类负责实现Serializable接口的java对象的序列化?

    这个过程的入口点是什么?谁调用 ObjectOutputStream?

  2. 即使没有实现Externalizable 接口,我的类的私有方法:readObjectwriteObject 已被调用。这些已在上面的代码中注释以启用默认的 Java Serializaiton。为什么在没有明确实现Externalizable 接口的情况下首先允许它?

编辑:为了明确我的问题,为什么 Java 允许私有 readObject & writeObject 方法而不是强制使用 Externalizable 实现来自定义序列化过程。

来自 Java 文档:

Externalizable 接口的 writeExternal 和 readExternal 方法由一个类实现,以使该类可以完全控制对象及其超类型的流的格式和内容。这些方法必须显式地与超类型协调以保存其状态。这些方法取代了 writeObject 和 readObject 方法的自定义实现。

两种机制都没有达到相同的结果吗?

【问题讨论】:

  • 这可能是 Java 中最具争议的设计决策之一。 Java 序列化 API 是 Magic (TM),其所有内部结构都是 JVM 实现细节。
  • 你好纪尧姆 girod-vitouchkina。即使那个问题也没有提供关于谁启动序列化过程的见解。每个人都说它自动符合条件。我的第二个问题也没有在那里得到回答。
  • @BoristheSpider 都是在对象序列化规范中定义的。没有魔法。

标签: java serialization


【解决方案1】:

负责序列化对象的类是java.io.ObjectOutputStream。反序列化在 java.io.ObjectInputStream 类中完成。

ObjectOutputStream 类的 JavaDoc 也包含以下内容:

在序列化和反序列化过程中需要特殊处理的类必须实现具有这些确切签名的特殊方法:

private void readObject(java.io.ObjectInputStream stream)
   throws IOException, ClassNotFoundException;
private void writeObject(java.io.ObjectOutputStream stream)
   throws IOException;
private void readObjectNoData()
   throws ObjectStreamException;

这里有一些伪代码显示了 ObjectOutputStream 的工作原理。我省略了很多细节,部分工作在 ObjectStreamClass 中完成。

class ObjectOutputStream {

    writeObject(obj) {
        writeObject0(obj);  
    }

    writeObject0(obj) {
        if (hasWriteReplaceMethod(obj)) {
            obj = obj.writeReplace();
        }
        writeOrdinaryObject(obj);
    }

    writeOrdinaryObject(obj) {
        if (isExternalizable(obj)) {
            writeExternalData(obj);
        } else {
            writeSerialdata(obj);
        }
    }

    writeExternalData(obj) {
        obj.writeExternal(this);
    }

    writeSerialData(obj) {
        if hasWriteObjectMethod(obj)
            obj.writeObject(this);
        else
            defaultWriteFields(obj);
    }
}

【讨论】:

  • 您的声明对于实现 Externalizable 接口是正确的。我正在寻找带有标记接口 Serializable 的序列化入口点而不实现这些方法以及如何在没有显式实现该 Externalizable 接口的情况下调用 readObject 和 writeObject。
  • 那我一定是一直在做错事。到目前为止,我已经用 ObjectOutputStream.writeObject() 序列化了我所有的可序列化类,但它们都没有实现 Externalizable 接口。
  • 删除那些方法并通过仅实现标记接口 Serializable 来测试代码。您的类将在不实现这两种方法的情况下进行序列化。已经为您提供了这些方法来自定义序列化。
  • @ravindra 此答案中没有任何内容取决于Externalizable。您的第二条评论中的程序并不能证明其他情况。
  • 我知道 API 在 Externalizable 中是不同的。但是为什么有两种机制:一种有明确的规范,另一种有后门?让事情变得明确会更好。
【解决方案2】:

哪个类启动序列化过程?

java.io.ObjectOutputStream.

  1. 通过在我的代码中实现标记接口Serializable,Java 正在序列化我的对象。哪个类负责实现Serializable接口的java对象的序列化?

java.io.ObjectOutputStream,再次。你似乎在寻找一些不存在的神奇事物。

  1. 即使没有实现Externalizable 接口,我的类的私有方法:readObjectwriteObject 已被调用。这些已在上面的代码中注释以启用默认的 Java Serializaiton。为什么在没有明确实现Externalizable 接口的情况下首先允许它?

您命名的方法与Externalizable 接口无关,它包含两个完全不同的方法。您的问题的答案很简单,它就是这样设计的,以便在不需要Externalizable 接口的情况下允许一定程度的自定义序列化,并且它是通过反射实现的。

为什么 Java 允许私有 readObject & writeObject 方法而不是强制使用 Externalizable 实现来自定义序列化过程。

它们不等价,所以这个问题没有意义。在 Serializable 级别,Java 提供了自动处理本地和父级非瞬态状态,而在 Externalizable 中,您必须完全自己完成。

两种机制都没有达到相同的结果吗?

没有。

【讨论】:

  • 在序列化过程中我仍然觉得有些神奇。我想知道java.io.ObjectOutputStream的调用者(入口点),谁负责这个过程。
  • 你的代码是调用者,你调用的“入口点”是writeObject()方法。而且,正如我已经说过的,这不是魔术,而是反射。
  • 嗯。我正在查看一些类,它检查这个对象是 Serializable 还是 Externizable 并调用相应的 API 进行序列化。
  • 寻找for这样的课程,你的意思是?一样的答案。 java.io.ObjectOutputStream。同样,你一直在寻找根本不存在的魔法。
  • 我现在对这个查询很清楚 :) 当 Externalizable 到位时,仍然不相信私有方法的其他查询。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-10-24
  • 1970-01-01
  • 1970-01-01
  • 2022-01-21
  • 2019-08-04
  • 2011-10-31
  • 2010-12-08
相关资源
最近更新 更多