如果Serializable
接口只是一个用于传递某种关于java类的元数据的标记接口- 我有点困惑:
看了java的序列化算法的流程(元数据自下而上,然后实际实例数据自上而下),实在无法理解通过那个算法不能处理哪些数据。
简而言之,正式:
- 哪些数据可能导致
NotSerializableException
? - 我怎么知道我不应该
implements Serializable
为我的班级添加条款?
如果Serializable
接口只是一个用于传递某种关于java类的元数据的标记接口- 我有点困惑:
看了java的序列化算法的流程(元数据自下而上,然后实际实例数据自上而下),实在无法理解通过那个算法不能处理哪些数据。
简而言之,正式:
NotSerializableException
?implements Serializable
为我的班级添加条款?当您谈论NotSerializableException
它时,当您想要序列化一个尚未标记为的对象时抛出它Serializable
- 仅此而已,尽管当您扩展不可序列化的类并添加Serializable
接口时它非常好。
没有不能序列化的数据。
首先,如果您不打算序列化您的类的实例,则甚至不需要考虑序列化它。只实现你需要的,不要仅仅为了它而试图让你的类可序列化。
如果您的对象具有对任何不可序列化对象的引用(传递或直接),并且该引用未使用transient
关键字标记,则您的对象将不可序列化。
通常,序列化以后或其他地方反序列化时无法重用的对象是没有意义的。这可能是因为对象的状态只在此时此地有意义(例如,如果它引用了正在运行的线程),或者因为它使用了一些资源,如套接字、数据库连接或类似的东西。很多对象不代表数据,也不应该是可序列化的。
您的Serializable
班级中没有的任何内容Serializable
都会引发此异常。您可以通过使用transient
关键字来避免它。
无法序列化的事物的常见示例包括 Swing 组件和线程。如果您考虑一下,这是有道理的,因为您永远无法反序列化它们并使其有意义。
所有原始数据类型和类都直接扩展Serializable ,
class MyClass extends Serializable{
}
或间接地,
class MyClass extends SomeClass{
}
SomeClass 实现了可序列化。
可以序列化。可序列化类中的所有字段都被序列化,除了标记的字段transient
。如果一个可序列化的类包含一个不可序列化的字段(不是原始的并且不从可序列化接口扩展),那么NotSerializableException
将被抛出。
回答第二个问题:正如@JB Nizet 所说。如果您要将类的实例写入某个流,然后只将其标记为可序列化,否则永远不要标记类可序列化。
看了java的序列化算法的流程(元数据自下而上,然后实际实例数据自上而下),实在无法理解通过那个算法不能处理哪些数据。
对此的答案是某些系统级类,例如 Thread、OutputStream 及其不可序列化的子类。在oracle文档上解释的很好:http ://www.oracle.com/technetwork/articles/java/javaserial-1536170.html
以下是摘要:
另一方面,某些系统级类,如 Thread、OutputStream 及其子类和 Socket 是不可序列化的。确实,如果它们是,那将没有任何意义。例如,在我的 JVM 中运行的线程将使用我系统的内存。坚持它并试图在你的 JVM 中运行它根本没有意义。
NotSerialisable
当您的可序列化中的某些内容标记为可序列化时,将引发异常。一种这样的情况可以是:
class Super{}
class Sub implements Serializable
{
Super super;
这里 super 没有被提及为可序列化的,所以会抛出NotSerializableException
。
更实际地,任何对象都不能被序列化(通过 Java 的内置机制),除非它的类实现了 Serializable 接口。然而,作为此类的一个实例并不是一个充分条件:要成功序列化一个对象,它拥有的所有非瞬态引用必须为空或引用可序列化对象也必须是真的。(请注意,这是一个递归条件。)原始值、空值和瞬态变量都不是问题。静态变量不属于单个对象,因此它们也不存在问题。
一些常见的类是可靠的序列化安全的。字符串在这里可能是最值得注意的,但原始类型的所有包装类也是安全的。原语数组是可靠可序列化的。如果引用类型的所有元素都可以序列化,则可以序列化引用类型数组。
哪些数据可能导致 NotSerializableException?
在 Java 中,我们序列化对象(已经实现了Serializable 接口的 Java 类的实例)。所以很明显,如果一个类没有实现Serializable 接口,就不能被序列化(那么就会抛出NotSerializableException )。
Serializable 接口只是一个标记接口,在某种程度上我们可以说它只是一个类上的一个标记,它只是告诉 JVM 该类可以被序列化。
我怎么知道我不应该为我的班级添加 implements Serializable 子句?
这一切都取决于您的需要。
如果要将Object存储在数据库中,可以将其序列化为字节序列,并将其作为持久数据存储在数据库中。
您可以序列化您的对象以供在不同机器上工作的其他 JVM 使用。