代码之家  ›  专栏  ›  技术社区  ›  Miserable Variable

是否认为显式SerialVersionId有害?

  •  24
  • Miserable Variable  · 技术社区  · 16 年前

    在这个问题上,我可能会冒着被否决的风险。

    在应该更改的时候不更改几乎只有在显式更改时才会发生。在这种情况下,它会导致一些非常微妙、难以发现的错误。尤其是在开发过程中,当类布局经常改变时。但是,如果没有明确指定,它将发生更改,反序列化将被大声中断,很可能通过清除存储库来解决。

    在不应该改变它的时候改变它几乎只有在它是隐式的时候才会发生。这是一种罕见的情况,类布局已经改变,但我们仍然希望从旧的序列化blob反序列化。这可能会在QA过程中被发现( )可以通过设置显式值来轻松修复。

    评论?

    6 回复  |  直到 16 年前
        1
  •  21
  •   Jon Skeet    16 年前

    在不应该发生更改时进行更改可能是由于类布局更改以外的原因—问题在于它依赖于编译器实现。如果您使用Eclipse进行调试,但使用javac进行生产构建,那么 最终得到两组不兼容的数据。

        2
  •  5
  •   Yoni Roit    16 年前

    在我的工作中,我们明确禁止指定serialVersionUID,正是因为您提出的问题。

        3
  •  4
  •   james    16 年前

    为了进一步强调john skeet所说的内容并反驳该评论:

    即使您不是长期序列化并且使用相同的类版本, . 如果您正在编写客户机-服务器代码,并且客户机代码可能运行与服务器不同的jvm版本/实现,那么您可能会遇到与不兼容的SerialVersionUID相同的问题。

    不指定serialversionuids“安全”的时间是在您不进行长期序列化并且可以保证序列化数据的所有使用者将使用与原始生产者相同的jvm实现和版本时。

    使用serialversionuid通常是更有害的情况。

        4
  •  2
  •   Joachim Sauer    16 年前

    serialVersionUID ,否则较旧的序列化版本将无法由较新的代码反序列化。

    当类发生更改时,这些场景已经需要非常小心才能正确处理所有情况,因此serialVersionUID是您的问题中最小的。

    如果您不需要(即,您总是使用相同的类版本进行序列化和反序列化),那么您可以安全地跳过显式声明,因为计算值将确保使用正确的版本。

        5
  •  1
  •   Tom Hawtin - tackline    16 年前

    serialVersionUID 或不(我建议你这样做),那么你真的应该考虑为串行兼容性创建一套全面的测试。

        6
  •  1
  •   stephan f    13 年前

    如果您只是在远程方法调用中使用序列化,例如调用EJB,其中客户机和服务器类以及jvm是相同的,我怀疑这是目前为止最常用的,那么显式设置serialVersionUID(例如eclipse建议的)很可能会以偶发性,无法解释的错误,不兼容的类实例由于固定的serialVersionUID而被视为兼容。远程调用在低级别序列化期间会悄悄出错,只有当对象的状态不一致时,问题才会出现。只有当您意识到客户机类和服务器类在某种程度上有所不同时(尽管serialVersionUID当然不是),您才能找到问题的根源。根据我的经验,出于这个原因设置serialVersionUID弊大于利。

    另一方面,如果显式地将serialVersionUID设置为读取旧数据,则根据定义,您正在读取不兼容的版本,并且很可能最终导致对象处于不一致或不完整的状态。在这种情况下,设置serialVersionUID是另一个问题的解决方法。