序列化之间的区别是什么,只是将对象存储在磁盘上?

我对此感到困惑。 从执行Serializable类开始,我们需要使用类FileOutputStreamObjectOutputStream等类。 那么为什么我们不只是使用这些类来做一些事情,比如将对象输出到文件并从文件中输入对象以直接维护对象的状态? 我们为什么要首先实现Serializable然后做同样的事情?

像这样理解它……

Serializable是标记接口,表示您的类的对象可以转换为字节流,并在需要时最终返回到java对象。 最初你可能认为每个类都应该是可序列化的,但这是不正确的考虑

Input-和OutputStreams有一些文件句柄可供读取。 当流变得不可用时,该文件句柄被关闭。 所以这个实例的序列化没有意义; 并且反序列化永远不会恢复该句柄。

那么这应该回答为什么需要标记为Serializable?

现在实现定义如何写入或读取对象的方法; 应该由您定义,因此您需要所有这些流对象和readObject,writeObject方法。 希望这能让您对这个概念有更多的了解。

Serializable只是一个标记接口,这意味着它只是用于向代码发出信号,这些代码将实际执行您(程序员)知道(或希望:-))的序列化,这个类可以无序地序列化。

序列化本身就是将对象转换为可以存储或传输的东西 – 也就是说,作为字节流。 你可以比较序列化和freezedrying,用于制作雀巢咖啡的技术 – 除去所有的水,只有咖啡精华存储在jar子里 – 只有一个对象的状态(字段值)被转换成字节流,而不是它的方法。

正如fvu已经说过的,序列化是将类的实例转换为字节数组的过程,反之亦然。 并非Java中的每个类都可以转换为字节数组(想想Thread类,将线程转换为字节数组是没有意义的)这就是你(和我们)需要实现它的原因。 Serializable在可转换的对象中进行Serializable

Serializable只是一个标记接口,它不需要任何方法来实现。 在大多数情况下,这已经足够了:只需使可序列化对象实现接口,然后使用默认行为。

该默认序列化行为在ObjectInputStreamObjectOutputStream类中实现。 FileInputStreamFileOutputStream是不同的类,用于从磁盘上的文件读取和写入数据。

如果要将对象写入磁盘,则需要使用以下内容:

 MyObject obj = ... // your object instance ObjectOutputStream stream = new ObjectOutputStream(new FileOutputStream("/path/to/file")); stream.writeObject(obj); 

要回读对象,您需要这样:

 ObjectInputStream stream = new ObjectInputStream(new FileInputStream("/path/to/file")); MyObject obj = (MyObject) stream.readObject(); 

但有时你会想要将对象实例序列化/反序列化到内存而不是磁盘,然后你将使用这样的东西:

 MyObject obj = ... // your object instance ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(baos); oos.writeObject(obj); byte[] data = baos.toByteArray(); 

我将省略从字节数组中读取对象的部分,因为它非常简单,但可以考虑使用JVM提供的所有不同输入/输出流的巨大组合。


上面的示例使用默认的序列化行为。 但是,您可能会面临这样的情况,其中您要序列化的给定类包含对未实现Serializable接口的其他类实例的引用,因此,我们如何序列化它们? 我们需要使用transient修饰符标记这些引用,因此默认的序列化行为将忽略它们,我们需要覆盖默认行为,提供在尝试序列化/反序列化对象实例时将调用的私有readObjectwriteObject方法。

另外,当序列化发生时,一些类可以提供替换对象(不同可序列化类的对象实例)。 该替换对象将包含原始类的状态,其中原始类可以从该替换对象恢复。 实现此行为是在原始类中提供writeReplace方法,在替换类中提供readReplace 。 请注意, 原始类和替换类都必须实现Serializable接口,但只有替换对象中的数据才会被序列化

最后但并非最不重要的是,可以选择完全覆盖实现Externalizable接口的默认序列化协议。 这不是Serializable的标记接口,您必须实现将对象的状态转换为数组的方法,反之亦然。 您仍将使用ObjectInputStream / ObjectOutputStream对来序列化( 外部化)可外部化的对象实例,但现在将类转换为字节数组的逻辑不再是JVM提供的逻辑,而是您在实现Externalizable类时的类。

所有这些信息都在thinksteep作为评论提供的链接中。

序列化是获取对象并将其写入字节数组(稍后从字节数组读取到对象)的过程

ObjectOutputStream在内部使用序列化,它使用serialize将对象转换为byte []并将其写入其输出