【问题标题】:How private writeObject method of Serializable object called by object of ObjectOutputStreamObjectOutputStream 对象如何调用 Serializable 对象的私有 writeObject 方法
【发布时间】:2023-03-26 07:15:01
【问题描述】:

当我运行这个演示时,它会调用 TestBean 的 writeObject 私有方法

这怎么可能?

代码如下:

import java.io.FileOutputStream;

public class Test {

    public static void main(String[] args) {

        try {
            TestBean testBean = test.new TestBean();

            testBean.setSize(23);
            testBean.setWidth(167);

            FileOutputStream fos =
                new FileOutputStream(new File("d:\\serial.txt"));
            ObjectOutputStream oos = new ObjectOutputStream(fos);
            oos.writeObject(testBean);

            oos.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    class TestBean implements Serializable {

        private static final long serialVersionUID = 1L;

        private int size;
        private int width;

        public int getSize() {
            return size;
        }

        public void setSize(int size) {
            this.size = size;
        }

        public int getWidth() {
            return width;
        }

        public void setWidth(int width) {
            this.width = width;
        }

        private void writeObject(ObjectOutputStream out) throws IOException {
            System.out.println("TestBean writeObject");
            out.defaultWriteObject();
        }

        private void readObject(ObjectInputStream input) throws IOException,
                                                                ClassNotFoundException {
            System.out.println("TestBean readObject ===================> ");
            input.defaultReadObject();
        }
    }
}

【问题讨论】:

  • 它调用 oos.writeObject(testBean);而不是 testBean.writeObject();
  • 但oos.writeObject(testBean) 会调用testBean.writeObject()(如果存在)。没有答案。

标签: java serialization


【解决方案1】:

如果您的可序列化对象有任何 writeObject 方法,它将被调用,否则将调用 defaultWriteObject 方法。

使用反射可以调用私有方法。如果您在该方法 writeSerialData 中看到 ObjectOutputStream 类的源代码,则下面的代码回答了您的问题。

if (slotDesc.hasWriteObjectMethod()) {
 // through reflection it will call the Serializable objects writeObject method
} else {
// the below is the same method called by defaultWriteObject method also.
writeSerialData(obj, desc);
}

【讨论】:

    【解决方案2】:

    虚拟机会自动检查是否有两种方法 在相应的方法调用期间声明。虚拟机 可以随时调用您的类的私有方法,但不能调用其他方法 对象可以。因此,类的完整性得到了维护,并且 序列化协议可以继续正常工作。这 序列化协议总是以相同的方式使用,通过调用 ObjectOutputStream.writeObject() 或 ObjectInputStream.readObject()。 因此,即使提供了那些专门的私有方法, 就任何调用对象而言,对象序列化的工作方式相同 很担心。

    您将从这篇文章中获得更多信息:

    Discover the secrets of the Java Serialization API

    【讨论】:

      【解决方案3】:

      它使用反射。私人和公共不是安全措施。这只是类用户的合同。

      【讨论】:

      • 不正确。它们是可以通过反射被有权这样做的代码覆盖的安全措施。
      • @EJP。我不认为他们是。这不像说您无法解决的公钥加密。对我来说,他们定义了类消费者可用的合同以及内部实现细节的合同。请看stackoverflow.com/questions/8357469/…
      猜你喜欢
      • 2016-02-23
      • 2014-04-16
      • 2015-09-16
      • 2018-09-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多