3

它让我对Serializable界面的启动感到困惑,为什么我必须将此字段合并到我的所有课程中。我知道这个接口需要一个唯一的标识符来标记这个类,但是为什么他们不能在运行时生成它。例如,他们可以使用完全限定类名的 MD5 散列或用于处理罕见情况下的重复项的类似方法来生成它(我敢肯定,当被要求生成 id 时,eclipse 会做什么)。

那么我要问的是(不,这篇文章不仅仅是对标准库的咆哮)框架到底是如何使用序列化字段的?

我想知道的原因是因为我将尝试创建一个 Aspect(用 AspectJ 或其他语言),它将使用 MD5 哈希添加 serialVersionUID 字段,并且能够以 API 可接受的方式处理冲突。

如果我能让它工作,我会发布结果。

4

4 回答 4

9

没有要求拥有该serialVersionUID领域。如果您不提供,Java 将根据您的类的字段和方法生成一个。

您可能要指定的原因serialVersionUID是为了防止在更改方法时更改值,这不会影响序列化的二进制文件。考虑类:

public class Person implements Serializable {
    private String name;
    public String getName() {
        return name;
    }
}

没有serialVersionUID指定。如果你运行serialver Person它返回:

Person:    static final long serialVersionUID = 3793453319058452486L;

现在您决定添加一个方法,但保持字段不变。

public class Person implements Serializable {
    private String name;
    public String getName() {
        return name;
    }
    public Object foo() {
        return "bar";
    }
}

序列化的二进制文件仍然与旧版本完全兼容,但serialVersionUID不同的是:

Person:    static final long serialVersionUID = -6188734029437600310L;

使用不同的serialVersionUID,反序列化将导致 serialVersionUID 不匹配错误。serialVersionUID解决方法是通过将其设置为任何值(我设置它)来声明您自己的值1L,并在字段发生更改时更改它。

另请参阅此相关问题“什么是 serialVersionUID,我为什么要使用它?” 进行更详细的讨论。

于 2012-09-07T01:12:08.110 回答
4

为什么我必须在我所有的课程中加入这个领域

你没有。

为什么他们不能在运行时生成这个

他们会这样做,除非你自己提供。

我将尝试创建一个 Aspect(在 AspectJ 或其他语言中),它将使用 MD5 哈希添加 serialVersionUID 字段

那将毫无意义。你不明白它是干什么用的。在运行时生成它是默认情况下已经发生的,因此您的提案没有任何价值。该值在编译时指定它,以便吸收实际上不会破坏对象版本控制兼容性的次要类更改。您无法通过 AOP 来实现这一点。这是一个编码决定。

于 2012-09-07T01:19:18.303 回答
0

正如@Steve Kuo 所提到的,不需要该serialVersionUID字段。

这是令人沮丧的,因为它没有作为对象可序列化合同的一部分强制执行,我们团队中大约一半的开发人员这样做,而另一半则没有。大多数通常只是设置private static final long serialVersionUID = 1L;(尽管一些开发人员喜欢利用它作为尝试提出伪随机 Longs 的机会......)

话虽如此,我一直认为这是对可序列化对象进行版本控制的初步尝试。

假设我们有:

public class PersonDTO implements Serializable {

    private static final long serialVersionUID = 1L;

    private String firstName;
    private String lastName;

    // Appropriate getters/setters of course
}

后来我们要添加一个新字段,private String middleInitial.

如果我们将 serialVersionUID 增加到 2,我们可以使用它来指示类已更改,并且旧的已序列化的具有 serialVersionUID 的 PersonDTO 实例无法使用此修改后的类定义反序列化。

于 2012-09-07T01:27:15.037 回答
0

Serializable界面_

该接口存在于java.io包中。这是为了保护较小的更改而实现的,并且是为了使用户能够writesave运行时访问对象。这个接口由所有的 swing 组件实现,因为开发者可以扩展它们,以便 JVM 可以找到组件的新版本,即Your class

SerialVersionUID

serialVersionUID用作 Serializable 类中的版本控制。如果您没有JVM will did it for you automatically根据您的 Serializable 类的各个方面显式声明一个 serialVersionUID,如Java(TM) Object Serialization Specification

于 2012-09-07T01:21:39.030 回答