当缺少serialVersionUID时,Eclipse会发出警告。

可序列化类Foo未声明静态finallong类型的serialVersionUID字段

什么是serialVersionUID,为什么它很重要?请显示缺少serialVersionUID将导致问题的示例。


当前回答

如果您在一个从未想过序列化的类上收到此警告,并且您没有声明自己实现了Serializable,这通常是因为您继承了一个实现Serializable的超类。通常情况下,最好委托给这样的对象,而不是使用继承。

所以

public class MyExample extends ArrayList<String> {

    public MyExample() {
        super();
    }
    ...
}

do

public class MyExample {
    private List<String> myList;

    public MyExample() {
         this.myList = new ArrayList<String>();
    }
    ...
}

并且在相关方法中调用myList.foo()而不是this.foo()(或super.foo(())

我经常看到有人在扩展JFrame之类的东西,而实际上他们只需要授权。(这也有助于在IDE中自动完成,因为JFrame有数百个方法,当您想在类中调用自定义方法时,不需要这些方法。)

警告(或serialVersionUID)不可避免的一种情况是,从AbstractAction(通常在匿名类中)扩展时,只添加actionPerformed方法。我认为在这种情况下不应该有警告(因为你通常无法可靠地序列化和反序列化这些匿名类,不管是在你的类的不同版本中),但我不确定编译器如何识别这一点。

其他回答

SerialVersionUID用于对象的版本控制。也可以在类文件中指定serialVersionUID。不指定serialVersionUID的结果是,当您添加或修改类中的任何字段时,已经序列化的类将无法恢复,因为为新类和旧序列化对象生成的serialVersionID将不同。Java序列化过程依赖于正确的serialVersionUID来恢复序列化对象的状态,并在serialVersionID不匹配的情况下抛出Java.io.InvalidClassException

阅读更多信息:http://javarevisited.blogspot.com/2011/04/top-10-java-serialization-interview.html#ixzz3VQxnpOPZ

为什么在Java中的Serializable类中使用SerialVersionUID?

在序列化期间,Java运行时为类创建一个版本号,以便以后可以对其进行反序列化。此版本号在Java中称为SerialVersionUID。

SerialVersionUID用于序列化数据的版本。只有当类的SerialVersionUID与序列化实例匹配时,才能对其进行反序列化。当我们不在类中声明SerialVersionUID时,Java运行时会为我们生成它,但不建议这样做。建议将SerialVersionUID声明为私有静态最终长变量,以避免默认机制。

当您通过实现标记接口java.io.Serializable将类声明为Serializable时,如果您没有使用Externalizable接口自定义进程,java运行时将该类的实例通过默认Serialization机制持久化到磁盘中。

另请参阅为什么在Java中的Serializable类中使用SerialVersionUID

要理解字段serialVersionUID的重要性,应该了解序列化/反序列化的工作原理。

当序列化一个Serializable类对象时,Java Runtime将一个序列版本号(称为serialVersionUID)与这个序列化对象相关联。在反序列化此序列化对象时,Java Runtime将序列化对象的serialVersionUID与类的serialVersion UID匹配。如果两者都相等,则只有它继续执行进一步的反序列化过程,否则抛出InvalidClassException。

因此,我们得出结论,要使序列化/反序列化过程成功,序列化对象的serialVersionUID必须与类的serialVersion UID等效。如果程序员在程序中显式指定serialVersionUID值,那么无论序列化和反序列化平台如何,相同的值都将与序列化对象和类相关联(例如,可以使用sun或MS JVM在类似windows的平台上进行序列化,而反序列化可以使用Zing JVM在不同的平台Linux上进行)。

但是,如果程序员未指定serialVersionUID,则在对任何对象进行Serialization\DeSerialization时,Java运行时会使用自己的算法来计算它。这种serialVersionUID计算算法因JRE而异。对象序列化的环境也可能使用一个JRE(例如:SUN JVM),而取消序列化的环境则使用LinuxJvm(zing)。在这种情况下,与序列化对象关联的serialVersionUID将不同于在取消序列化环境中计算的类的serialVersion UID。反过来,反序列化将不会成功。所以为了避免这种情况/问题,程序员必须始终指定Serializable类的serialVersionUID。

首先回答您的问题,当我们不在类中声明SerialVersionUID时,Java运行时会为我们生成它,但该过程对许多类元数据敏感,包括字段数、字段类型、字段的访问修饰符、类实现的接口等。因此,建议我们自己声明它,Eclipse也会警告您。

序列化:我们经常处理状态(对象变量中的数据)非常重要的重要对象,因此在将对象状态发送到其他机器时,我们不会因电源/系统故障(或网络故障)而丢失它。这个问题的解决方案被命名为“持久性”,这意味着持久化(保存/保存)数据。串行化是实现持久性的许多其他方法之一(通过将数据保存到磁盘/内存)。保存对象的状态时,为对象创建标识,以便能够正确地将其读回(反序列化),这一点非常重要。此唯一标识ID为SerialVersionUID。

您可以告诉Eclipse忽略这些serialVersionUID警告:

窗口>首选项>Java>编译器>错误/警告>潜在编程问题

如果您不知道,您可以在本节中启用许多其他警告(甚至将一些警告报告为错误),其中许多警告非常有用:

潜在的编程问题:可能的意外布尔赋值潜在编程问题:空指针访问不必要的代码:从不读取局部变量不必要的代码:冗余空检查不必要的代码:不必要的强制转换或“instanceof”

以及更多。