0

我知道 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 是否是一个标记接口?

4

4 回答 4

1

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

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 方法中添加了字符串常量。

于 2013-03-11T12:52:25.150 回答
1

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

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

于 2013-03-11T12:43:18.563 回答
0

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

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

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

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

于 2013-03-11T12:53:06.150 回答
0

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

示例:如果您正在序列化 User.java,请在此类中提供以下方法用于自定义序列化: private void writeObject(java.io.ObjectOutputStream out) throws IOException private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException;

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

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

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

于 2015-12-21T09:18:16.077 回答