0

The main benefit of externalization over serialization is that externalization persists only part of the object, not the whole object as in case of serialization. But i think that we can simulate externalization via custom serialization if we will not call defaultWriteObject() method of ObjectOutputStream in writeObject() method of the serializable class. So without calliing defaultWriteObject() method and only persisting the needed instance variables of serializable class in writeObject() method we can achieve externalization benefits.

Here is an example demonstrating the aforementioned things:

package com.test;

import java.io.*;

public class Test {
    public static void main(String[] args) throws FileNotFoundException,     IOException, ClassNotFoundException {
        Dog dog = new Dog();
        System.out.println("before serialization: i = " + dog.i + ", j = " +     dog.j);

        FileOutputStream fos = new FileOutputStream("abc.ser");
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        oos.writeObject(dog);

        FileInputStream fis = new FileInputStream("abc.ser");
        ObjectInputStream ois = new ObjectInputStream(fis);
        Dog dog2 = (Dog) ois.readObject();
        System.out.println("after deserialization: i = " + dog2.i + ", j = " +      dog2.j);

    }

    public static class Dog implements Serializable {
        int i = 10;
        int j = 20;

        private void writeObject(ObjectOutputStream oos) throws IOException{
            //oos.defaultWriteObject();
            System.out.println("In WriteObject");
            oos.writeInt(i);
        }

        private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
            //ois.defaultReadObject();
            System.out.println("In ReadObject");
            i = ois.readInt();
        }
    }
}

The output for this code is:

before serialization: i = 10, j = 20
In WriteObject
In ReadObject
after deserialization: i = 10, j = 0

As you can see, the oos.defaultWriteObject() and ois.defaultReadObject(); are commented and we persist and restore only the instance variable i.

So, is my assumption correct that we can simulate externalization concept via custom serialization ?

4

1 回答 1

1

那么,我的假设是否正确,我们可以通过自定义序列化来模拟外部化概念?

您的假设是正确的,即程序员有能力为他选择的类构造任何序列化形式。

Serializable接口是一个标记接口,它向 Java 运行时环境发出信号,表明已为实现类启用了基于 Java 的序列化。如果您什么都不做,Java 运行时会调用默认的序列化工具,该工具会根据您的类的所有实例字段为您创建一个序列化表单。

一个类的最佳序列化形式是:

  • 仅描述其实例的逻辑状态
  • 不包含特定于实现的细节或元数据
  • 写入和读取流式传输和恢复类实例所需的最少信息

例如,在上面的代码中,如果两者都i描述j了对象的有意义状态,那么不包含的序列化形式j将是有缺陷的,因为您将无法在反序列化后将对象恢复到其有意义的状态。

但是,如果i描述了有意义的状态,但j它是不属于对象逻辑状态的一部分的实现细节,那么最好j从流中消除以获得更优化的序列化形式。

虽然默认的序列化形式(由内置的 Java 序列化工具发出)通常足以满足简单的值类,但更复杂的抽象包含不应成为其序列化形式的一部分的元数据和实现信息。

为了帮助程序员为他们的类设计最佳的序列化形式(如果默认形式不合适),Java 提供了两种广泛的机制来为对象生成最佳的序列化形式:

  • 定制序列化
  • Externalizable界面_

前一种策略允许程序员通过使用关键字来修改内置 Java 序列化工具的行为transient,并挂钩到诸如readObject()writeObject()readResolve()等方法中。对于具有必须不变量的不可变值类,特别推荐使用序列化代理。受到保护。

后一种策略让程序员实现Externalizable而不是SerializableExternalizable本身扩展Serializable)。与 不同,该Externalizable接口Serializable不是标记接口。它的方法在实现时旨在让程序员完全控制对象的序列化形式如何发出和恢复。

“与序列化相比,外化的主要好处是外化只保留对象的一部分,而不是像序列化那样保留整个对象。”

仅包含“对象的一部分”并且不包含重构对象在序列化之前存在的状态所需的所有信息的序列化形式是有缺陷的序列化形式。这种形式可能会在那些依赖序列化进行进程间通信的平台中引起问题。

于 2016-05-24T19:46:24.440 回答