【问题标题】:The Class Which implements Serializable needs to impliment some methods?实现 Serializable 的类需要隐含一些方法?
【发布时间】:2013-02-26 15:18:00
【问题描述】:

我知道 Serializable 是一个标记接口。那么下面的方法签名是什么意思呢?

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

这是来自http://docs.oracle.com/javase/6/docs/api/java/io/Serializable.html

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

我很困惑。 Serializable 是否是标记接口?

【问题讨论】:

  • 而且它们也是私有的! O_o

标签: java serialization serializable


【解决方案1】:

是的,Serializable 是一个标记接口。只有需要特殊处理的类必须实现这些方法。

换句话说,您可以实现这些方法中的一个或多个来自定义类的实例如何被序列化或反序列化。这通常不需要,因为默认行为足以满足大多数需求。

【讨论】:

    【解决方案2】:

    这些方法用于自定义序列化过程。我给你举个例子。

    class Person implements java.io.Serializable {
    
    int id;
    String name;
    String city;
    
    Person(int id, String name, String city) {
        this.id = id;
        this.name = name;
    this.city = city;
    }
    
    private void writeObject(java.io.ObjectOutputStream stream)
            throws IOException {
        stream.writeInt("ID : " + id);
        stream.writeObject("Name : " + name);
        stream.writeObject("City : " + city);
    }
    
    private void readObject(java.io.ObjectInputStream stream)
            throws IOException, ClassNotFoundException {
        id = stream.readInt();
        name = (String) stream.readObject();
        city = (String) stream.readObject();
    }
    
    public String toString() {
        return id + "\t" + name + "\t" + city + "\t";
    }
    }
    

    请注意,序列化是使用这些方法自定义的。在序列化默认序列化方法不会执行的字段时,我在 writeObject 方法中添加了字符串常量。

    【讨论】:

      【解决方案3】:

      我将在这里疯狂猜测原因。鉴于您可以使用标签来确定哪些字段是可序列化的,我的第一个想法是序列化的内部工作,例如在ObjectOutputStream 中,是通过反射完成的。

      因此,writeObject 方法实际上可能也在检查是否存在具有相同签名的私有方法,如果存在则调用该方法。最后,同样的方法已经使用反射来确定要序列化哪个字段以及如何序列化,所以我相信检查特殊方法的存在并不是一个巨大的开销......

      这可能看起来有点奇怪,但听起来是一个不错的解决方案。在接口中强制实现会太多,因为大多数时候是常见的。在像 Java 这样的单一继承模型中使用抽象类是不可能的。 C# 使用属性(相当于 Java 中的 @ 注释)。

      希望有更多知识的人能对此有所了解。 :)

      【讨论】:

        【解决方案4】:

        很简单。如果你想要自定义序列化,你可以在要序列化的类中提供上述方法。

        示例:如果您正在序列化 User.java,请在此类中提供以下方法以进行自定义序列化: 私有无效 writeObject(java.io.ObjectOutputStream 输出) 抛出 IOException private void readObject(java.io.ObjectInputStream in) 抛出 IOException,ClassNotFoundException;

        无论如何,当你通过objectOutputStream.writeObject(本例中的对象是User)调用对象的序列化时,控制将自动重定向到User.java的writeObject方法。

        如果您不提供 User.java 中的方法。然后该过程以默认方式进行。

        注意:如果您在要序列化的类中同时提供 writeObject/readObject 的实现,则只有自定义序列化有效,否则采用默认路由。 希望这会有所帮助!

        【讨论】:

          猜你喜欢
          • 2013-04-10
          • 1970-01-01
          • 2014-08-04
          • 2013-02-21
          • 2023-03-07
          • 1970-01-01
          • 1970-01-01
          • 2011-05-28
          相关资源
          最近更新 更多