这是啥意思:可序列化的类没有声明一个静态的最终 serialVersionUID 字段? [复制]

Posted

技术标签:

【中文标题】这是啥意思:可序列化的类没有声明一个静态的最终 serialVersionUID 字段? [复制]【英文标题】:What does it mean: The serializable class does not declare a static final serialVersionUID field? [duplicate]这是什么意思:可序列化的类没有声明一个静态的最终 serialVersionUID 字段? [复制] 【发布时间】:2011-01-18 08:06:27 【问题描述】:

我有标题中给出的警告信息。我想了解并删除它。我已经找到了关于这个问题的一些答案,但由于技术术语过多,我不明白这些答案。能不能用简单的话来解释这个问题?

附:我知道 OOP 是什么。我知道什么是对象、类、方法、字段和实例化。

P.P.S.如果有人需要我的代码,就在这里:

import java.awt.*;
import javax.swing.*;


public class HelloWorldSwing extends JFrame 

        JTextArea m_resultArea = new JTextArea(6, 30);

        //====================================================== constructor
        public HelloWorldSwing() 
            //... Set initial text, scrolling, and border.
            m_resultArea.setText("Enter more text to see scrollbars");
            JScrollPane scrollingArea = new JScrollPane(m_resultArea);
            scrollingArea.setBorder(BorderFactory.createEmptyBorder(10,5,10,5));

            // Get the content pane, set layout, add to center
            Container content = this.getContentPane();
            content.setLayout(new BorderLayout());
            content.add(scrollingArea, BorderLayout.CENTER);
            this.pack();
        

        public static void createAndViewJFrame() 
            JFrame win = new HelloWorldSwing();
            win.setTitle("TextAreaDemo");
            win.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            win.setVisible(true);
        

        //============================================================= main
        public static void main(String[] args) 
            SwingUtilities.invokeLater(new Runnable()
                public void run()
                    createAndViewJFrame();
                
            );
        


【问题讨论】:

可能是讨论的警告消息是我的 GUI 应用程序冻结的原因吗? 不,与您的 gui 冻结无关。 复制:***.com/questions/285793/… 【参考方案1】:

来自javadoc:

序列化运行时为每个可序列化类关联一个版本号,称为serialVersionUID,在反序列化期间使用该版本号来验证序列化对象的发送方和接收方是否已为该对象加载了与序列化兼容的类.如果接收者为对象加载了一个类,该类的serialVersionUID 与相应发送者的类不同,则反序列化将导致InvalidClassException。可序列化类可以通过声明一个名为 "serialVersionUID" 的字段来显式声明自己的 serialVersionUID,该字段必须是静态的、最终的和 long 类型:

您可以将 IDE 配置为:

忽略这一点,而不是发出警告。 自动生成 ID

根据您的附加问题“可能是所讨论的警告消息是我的 GUI 应用程序冻结的原因吗?”:

不,不可能。仅当您在类已更改的不同位置(或时间)对对象进行序列化和反序列化时才会导致问题,并且不会导致冻结,而是在InvalidClassException

【讨论】:

你也可以让你的IDE自动生成一个。 @BalusC - 我们如何在 Eclipse 中做到这一点?自动生成安全吗? @JediKnight 在 Eclispse 中是 Window>Preferences>Java>Code Style>Clean Up>Missing Code>在“Potential Programming Problems”下激活“Add serial version ID”。然后,如果您在默认配置文件中,显然您必须将其另存为其他配置文件。 不使用序列化时不要自动生成serialVersionUID。这已经在编译过程中发生了,而不必为了让你的 IDE 满意而用愚蠢的随机数毒害你的源代码。只需关闭 Eclipse 警告,因为这才是真正的混乱来源。如果您确实想使用序列化(这些天的可能性接近 0),请阅读它,并使用 serialVersionUID 作为版本号(从 1 开始,并在您的类定义使用特殊代码更改时递增阅读旧版本)。【参考方案2】:

到目前为止的其他答案有很多技术信息。根据要求,我会尽量简单地回答。

如果您想将对象的实例转储到原始缓冲区、将其保存到磁盘、以二进制流传输(例如,通过网络套接字发送对象)或其他方式,则序列化是您对对象实例执行的操作创建对象的序列化二进制表示。 (有关序列化的更多信息,请参阅Java Serialization on Wikipedia)。

如果你不打算序列化你的类,你可以在你的类上面添加注解@SuppressWarnings("serial")

如果您要进行序列化,那么您需要担心很多事情都围绕着正确使用 UUID。基本上,UUID 是一种对您将序列化的对象进行“版本化”的方法,以便任何正在反序列化的进程都知道它正在正确地反序列化。我会查看Ensure proper version control for serialized objects 以获取更多信息。

【讨论】:

你的引文有几个主要错误,也有一些自相矛盾的地方。 @EJP 如果您列举了错误,这将对所有人都有帮助。 @EJP 我突然想到我的回答中有两个引用。您指的是哪个引文? 我指的是 Javaworld 文章,但您的答案中唯一引用的是第三方资源,这些资源与本网站上的答案相比没有任何地位:通常要少得多。唯一的相关引用是规范性引用:JLS、JVM 规范、Java 对象序列化规范和 Javadoc。【参考方案3】:

警告的原因记录在here,简单的修复方法是关闭警告或在代码中添加以下声明以提供版本 UID。实际值无关紧要,如果愿意,可以从 999 开始,但是当您对类进行不兼容的更改时更改它。

public class HelloWorldSwing extends JFrame 

        JTextArea m_resultArea = new JTextArea(6, 30);
        private static final long serialVersionUID = 1L;

【讨论】:

Java 对象序列化规范和Javadoc 中记录了警告的原因。 *** 答案不是规范性参考。【参考方案4】:

任何时候都必须改变它 影响序列化的更改 (附加字段,删除字段, 更改字段顺序,...)

这是不正确的,您将无法引用该声明的权威来源。每当您根据Object Serialization Specification 的Versioning of Serializable Objects 部分中给出的规则进行不兼容的更改时,都应该更改它,具体包括额外的字段或字段顺序的更改,并且当你没有提供readObject(), writeObject(), 和/或readResolve()/writeReplace() 方法和/或serializableFields 声明来应对变化时。

【讨论】:

【参考方案5】:

任何可以序列化的类(即实现Serializable)都应声明该UID,并且只要有任何影响序列化的更改(附加字段、删除字段、更改字段顺序……),就必须更改它。反序列化时会检查该字段的值,如果序列化对象的值不等于当前VM中类的值,则抛出异常。

请注意,此值的特殊之处在于它与对象一起序列化,即使它是静态的,原因如上所述。

【讨论】:

我的 JFrame 是一个可序列化的类?什么是 UID 以及如何声明它?我的代码是否“更改了影响序列化的内容”?序列化究竟意味着什么? 是的,JFrame 是一个实现 Serializable 的 java.awt.Component。代码永远不会改变任何影响序列化的东西,只有程序员才会这样做。我不知道列出影响序列化的所有更改的列表。查看en.wikipedia.org/wiki/Serialization#Java 以获取 Java 中序列化的描述。 不与对象序列化。它不应该被改变,除非你想破坏兼容性,或者如果你已经这样做了,因为它偏离了规范的版本部分中所说的内容。这不包括添加或重新排序字段。正确的参考不是***而是对象序列化规范。 “附加字段、删除字段、更改字段顺序”根本不重要。如果您不实现 readObject() 来处理更改,则只有类型更改才重要。

以上是关于这是啥意思:可序列化的类没有声明一个静态的最终 serialVersionUID 字段? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

在 Boost.MPI 中使类可序列化是啥意思?

serializable 类 DrawImage 未声明类型为 long 的静态终态 是啥意思

c编程中,warning C4129: 's' : unrecognized character escape sequence这是啥意思

java this啥意思?

JSONArray jsonary = (JSONArray) JSONObject.parse(s); 是啥意思

iOS合并lib(.a)库的可用方法(可用于解决duplicate symbol静态库冲突)