【问题标题】:Java: What can and what can't be serialized?Java:什么可以序列化,什么不能序列化?
【发布时间】:2013-05-26 21:47:45
【问题描述】:

如果Serializable 接口只是一个Marker-Interface 用于传递某种关于Java 类的元数据——我有点困惑:

看完java的序列化算法的流程(元数据自下而上,然后实际实例数据自上而下),实在搞不懂有哪些数据不能通过那个处理算法。

简而言之:

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

【问题讨论】:

  • TL;DR:所以我认为我在这里从几个答案的组合中读到的是基本的 Java 类型是可序列化的,但如果你在一个类中有它们,那么那个类(或一个其父类)需要可序列化。如果任何类(或父类)没有明确标记为 Serializable,那么它不是。如果您将一个类标记为可序列化,那么它的所有成员都需要为自己遵循这些相同的规则。
  • 然而,如果一个类被标记为 Serializable,那么任何 member 类实例(该 Serializable 类的)包含 only Serializable作为其成员的类型,包括仅包含可序列化的其他类等,也将是可序列化的,无需显式声明。这是我从自己的代码中收集的。
  • @Andrew 参考关于“成员类”的最后一条注释 - 每个应该(并且可以......)序列化的类 - 都需要标记为可序列化。任何其他选择至少是一种非常糟糕的做法。

标签: java serialization marker-interfaces


【解决方案1】:

当您谈论NotSerializableException 时,当您想要序列化一个尚未标记为Serializable 的对象时会抛出 - 仅此而已,尽管当您扩展不可序列化的类并添加Serializable 接口时完全没问题。

没有不能序列化的数据。

【讨论】:

  • 唯一真正理解我的意思的:我不想知道什么时候使用'serializable'接口。我只是想了解哪些数据是可序列化的,哪些数据不是。如果你们中的一些人(@JB Nizet 等)实际上可以添加一个小解释:如果任何数据最终是由原语组成的——并且这些是可序列化的——为什么 java 人创建了这个接口?
  • @MordechayS Serializable 是一个标记接口,用于区分您想要序列化的对象和您不想序列化的对象。序列化时有许多类型的对象没有意义。例如Connection / File 等类型的对象。这些代表绑定到特定机器的资源,如果序列化则没有任何意义。因此标记界面。
  • @Michal Borek,你说得很好,没有不能序列化的数据,那我们为什么需要Serializable 属性,为什么不能序列化属性隐含行为(我只是古玩)。
  • @ShankarS 那是因为您可能希望禁止类的序列化。我当时的意思是你可以序列化任何对象,直到你提供适当的序列化机制。在某些情况下,您可能需要提供自定义序列化程序,在某些情况下,隐式序列化就足够了。 Java 是一种显式语言,通常您需要说明显而易见的内容 - 例如局部变量的类型(在较新的版本中往往会发生变化 - “var”关键字,但这仍然是 Java 的构建方式)。
【解决方案2】:

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

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

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

【讨论】:

    【解决方案3】:

    你的Serializable 类中的任何不是Serializable 的东西都会抛出这个异常。您可以使用 transient 关键字来避免它。

    无法序列化的常见示例包括 Swing 组件和线程。如果您考虑一下,这是有道理的,因为您永远无法反序列化它们并使其有意义。

    【讨论】:

      【解决方案4】:

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

      class MyClass extends Serializable{
      }
      

      或间接地,

      class MyClass extends SomeClass{
      }
      

      SomeClass 实现了 Serializable。

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

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

      【讨论】:

        【解决方案5】:

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

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

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

        【讨论】:

          【解决方案6】:

          看完java的序列化算法的流程(元数据自下而上,然后实际实例数据自上而下),我实在是搞不懂那个算法不能处理哪些数据。

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

          以下是摘要:

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

          【讨论】:

            【解决方案7】:

            NotSerialisable 当您的可序列化中的某些内容标记为可序列化时,将引发异常。一种这样的情况可以是:

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

            这里没有提到 super 是可序列化的,所以会抛出 NotSerializableException

            【讨论】:

              【解决方案8】:

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

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

              【讨论】:

              • 如果一个可序列化的类有一个不可序列化类的对象引用但为空,会发生什么。你能解释一下在序列化时如何处理 null 吗?
              【解决方案9】:

              哪些数据可能导致 NotSerializableException?

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

              Serializable 接口只是一个marker-interface,在某种程度上我们可以说它只是一个类上的一个标记,它只是告诉 JVM 该类可以被序列化。 p>

              我怎么知道我不应该添加工具 我的班级的可序列化子句?

              这一切都取决于你的需要。

              1. 如果你想将对象存储在数据库中,你可以 将其序列化为字节序列,并可以将其存储在 数据库作为持久数据。

              2. 您可以序列化您的 Object 以供其他 JVM 工作 在不同的机器上。

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2016-10-14
                • 2014-09-12
                • 1970-01-01
                • 2015-05-11
                • 1970-01-01
                • 2011-10-31
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多