它是什么意思:serializable类没有声明一个静态的final serialVersionUID字段?

Rom*_*man 208 java serializable serialversionuid

我在标题中给出了警告信息.我想了解并删除它.我在这个问题上找到了一些答案,但由于技术术语过载,我不理解这些答案.用简单的词语解释这个问题有可能吗?

PS我知道OOP是什么.我知道什么是对象,类,方法,字段和实例化.

PPS如果有人需要我的代码,它在这里:

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();
                }
            });
        }

}
Run Code Online (Sandbox Code Playgroud)

Boz*_*zho 151

来自javadoc:

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

您可以将IDE配置为:

  • 忽略这一点,而不是发出警告.
  • 自动生成一个id

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

不,它不可能.只有在序列化对象并在不同的地方(或时间)反序列化它们时,它才会导致问题,其中(类)更改了类,并且它不会导致冻结,但是会导致问题InvalidClassException.

  • 您也可以让IDE自动生成一个. (10认同)
  • @BalusC - 我们怎么能在日食中做到这一点?自动生成是否安全? (4认同)
  • @JediKnight在Eclispse中,它是Window> Preferences> Java> Code Style> Clean Up> Missing Code>激活"潜在编程问题"下的"添加串行版本ID".然后,如果您处于默认配置文件中,显然您必须将其另存为另一个配置文件. (4认同)
  • 不使用序列化时,不要自动生成“serialVersionUID”。这已经在编译期间发生了,而不必为了让您的 IDE 满意而使用愚蠢的随机数来毒害您的源代码。只需关闭 Eclipse 警告,因为那才是真正令人困惑的地方。如果您确实想使用序列化(这些天很可能接近 0),请阅读它,并将“serialVersionUID”用作版本号(从 1 开始,并在您的类定义随特殊代码更改时递增)阅读旧版本)。 (4认同)

Rob*_*bin 33

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

public class HelloWorldSwing extends JFrame {

        JTextArea m_resultArea = new JTextArea(6, 30);
        private static final long serialVersionUID = 1L;
Run Code Online (Sandbox Code Playgroud)

  • 警告的原因记录在Java对象序列化规范和[Javadoc](http://docs.oracle.com/javase/7/docs/api/java/io/Serializable.html)中.StackOverflow答案不是规范性引用. (2认同)

MrM*_*Mas 32

到目前为止,其他答案都有很多技术信息.我会按照要求简单地回答.

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

如果您无意序列化类,则可以在类的上方添加注释@SuppressWarnings("serial").

如果你要序列化,那么你有很多事情要担心所有都围绕正确使用UUID.基本上,UUID是一种"版本化"您将序列化的对象的方法,这样无论什么进程反序列化都知道它正确地反序列化.我将查看确保序列化对象的正确版本控制以获取更多信息.

  • @EJP如果您列举了错误,那将对所有人有所帮助. (12认同)

use*_*421 27

每当影响序列化的任何更改(其他字段,删除的字段,字段顺序更改,......)时,必须更改它

这不正确,您将无法引用该声明的权威来源.每当你做出改变是根据在给定的规则不兼容应当改变序列化的对象的版本的的部分对象序列化规范,其特异性地并包括额外的字段或字段顺序的变化,并且当没有提供readObject(), writeObject(),和/或readResolve()/writeReplace()方法和/或serializableFields可能与应对变化的声明.


Tho*_*zer 5

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

请注意,由于上述原因,该值是特殊的,因为它是对象序列化的,即使它是静态的.

  • 我JFrame是一个可序列化的类?什么是UID以及我如何声明它?我的代码"会改变影响序列化的东西"吗?实际上序列化意味着什么? (2认同)
  • 它没有与对象序列化.除非您想要破坏兼容性,或者如果您已经通过偏离规范的版本控制部分中所说的内容,则不应更改它.这不包括添加或重新排序字段.正确的参考不是维基百科,而是对象序列化规范. (2认同)