Java:什么可以和什么不能序列化?

如果Serializable接口只是一个标记接口 ,用于传递关于java中类的某些元数据 – 我有点困惑:

在阅读了java的序列化算法(元数据从下到上,然后是从上到下的实际实例数据)的过程之后,我无法真正理解通过该算法无法处理哪些数据。

简而言之:

  1. 哪些数据可能导致NotSerializableException
  2. 我怎么知道我不应该为我的类添加implements Serializable子句?

当你谈论NotSerializableException时,当你想要序列化一个没有被标记为Serializable的对象时就会抛出它 – 这就是全部,尽管当你扩展非可序列化的类,并添加Serializable接口时它是完全没问题的。

没有数据无法序列化。

首先,如果您不打算序列化类的实例,则无需考虑序列化它。 只实现你需要的东西,不要试图让你的类可序列化只是为了它。

如果您的对象具有对任何非可序列化对象的引用(传递或直接),并且此引用未使用transient关键字标记,则您的对象将不可序列化。

通常,序列化在以后或其他地方反序列化时无法重用的对象是没有意义的。 这可能是因为对象的状态仅在此处有意义(例如,如果它具有对正在运行的线程的引用),或者因为它使用某些资源,如套接字,数据库连接或类似的东西。 很多对象不代表数据,不应该是可序列化的。

序列化 – 将数据转换为字节流

反序列化 – 将字节流重新转换为原始对象的副本。

JAVA中的序列化 : – Serializable是一个标记接口,它告诉JVM可以将对象的状态写出到某个流(基本上读取所有成员,并将其状态写入流,或写入磁盘或其他内容)。 默认机制是二进制格式。 您还可以使用它来克隆事物,或者在调用之间保持状态,通过网络发送对象等。

短暂的: –

Java中的关键字transient用于表示不应序列化变量。 默认情况下,对象中的所有变量都将转换为持久状态。 在某些情况下,您可能希望避免持久化某些变量,因为您没有必要通过网络进行传输。 因此,您可以将这些变量声明为瞬态变量。 如果变量被声明为瞬态变量,那么它将不会被持久化。 这是transient关键字的主要目的。

java中的瞬态关键字比任何其他关键字(例如volatile)更不常见。因为瞬态不太常见,所以理解它的正确用法变得更加重要。 在一个词中,在序列化过程中使用transient关键字来防止任何变量被序列化,因此如果您有任何无序序列化的字段,您可以简单地将其声明为瞬态并且不会被序列化。

您的Serializable类中包含的任何不可Serializable都会引发此exception。 您可以使用transient关键字来避免它。

您无法序列化的常见示例包括Swing组件和Threads。 如果你仔细想想它是有道理的,因为你永远不会反序列化它们并使它有意义。

所有原始数据类型和类都直接扩展Serializable ,

 class MyClass extends Serializable{ } 

或间接地,

 class MyClass extends SomeClass{ } 

SomeClass实现Serializable。

可以序列化。 可序列化类中的所有字段都被序列化,除了标记为transient的字段。 如果可序列化类包含不可序列化的字段(不是原始字段且不从可序列化接口扩展),则将抛出NotSerializableException

回答第二个问题:正如@JB Nizet所说。 如果要将类的实例写入某个流然后只将其标记为Serializable,否则永远不要标记Serializable类。

您需要处理自己的对象的序列化。

Java将为您处理原始数据类型。

更多信息: http : //www.tutorialspoint.com/java/java_serialization.htm

当序列化中的某些内容标记为可序列化时,抛出NotSerialisableexception。 一个这样的情况可以是:

 class Super{} class Sub implements Serializable { Super super; 

这里super不会被提及为serializable,因此会抛出NotSerializableException

在阅读了java的序列化算法(元数据从下到上,然后是从上到下的实际实例数据)的过程之后,我无法真正理解通过该算法无法处理哪些数据。

答案是某些系统级类,如Thread,OutputStream及其子类,这些类是不可序列化的。 在oracle文档中解释得非常好: http : //www.oracle.com/technetwork/articles/java/javaserial-1536170.html

以下是摘要:

另一方面,某些系统级类(如Thread,OutputStream及其子类和Socket)不可序列化。 实际上,如果它们是没有任何意义的话。 例如,在我的JVM中运行的线程将使用我系统的内存。 持久化并尝试在JVM中运行它根本就没有意义。

更实际地,除非其类实现Serializable接口,否则不能对象化(通过Java的内置机制)。 然而,作为这样一个类的实例并不是一个充分条件:对于一个成功序列化的对象,它所拥有的所有非瞬态引用必须为null或引用可序列化对象。 (请注意,这是一个递归条件。)原始值,空值和瞬态变量不是问题。 静态变量不属于单个对象,因此它们也不存在问题。

一些常见的类是可靠的序列化安全的。 字符串在这里可能是最值得注意的,但原始类型的所有包装类也是安全的。 基元数组是可靠的可序列化的。 如果可以序列化所有元素,则可以序列化引用类型的数组。

问题 – 哪些数据可能导致NotSerializableException?

答案 – 在java中我们序列化对象(已经实现了Serializable接口的java类的实例)。 所以很明显,如果一个类没有实现Serializable接口 ,它就不能被序列化(那么在那种情况下会抛出NotSerializableException )。

Serializable接口只是一个标记接口 ,我们可以说它只是一个类的标记,而且只是告诉JVM该类可以被序列化。


问题 – 我怎么知道我不应该为我的类添加实现Serializable子句?

答案 – 这完全取决于您的需求。

  1. If you want to store the *Object* in a database, you can serialize it to a sequence of byte and can store it in the database as persistent data. 2. You can serialize your *Object* to be used by other JVM working on different machine.