java.io.InvalidClassException: local class incompatible:编辑

我创建了客户端和服务器,然后在客户端添加了一个类以进行序列化,然后只需转到硬盘驱动器中客户端的文件夹并将其复制粘贴到服务器相应的位置即可,两者都是和分别。classname.classclassname.java

它在我自己的笔记本电脑中运行良好,但是当我想在其他系统上继续工作时,当我打开项目文件夹并在客户端尝试连接到服务器后,出现以下错误:

Exception in thread "main" java.io.InvalidClassException: projectname.clasname; local class incompatible: stream classdesc serialVersionUID = -6009442170907349114, local class serialVersionUID = 6529685098267757690
    at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:562)
    at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1582)
    at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1495)
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1731)
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1328)
    at java.io.ObjectInputStream.readObject(ObjectInputStream.java:350)

这是怎么回事?是因为我使用较旧版本的IDE运行了程序吗?

编辑

import java.io.Serializable;
import java.net.URL;

public class KeyAdr implements Serializable {
  private static final long serialVersionUID = 6529685098267757690L;

  public URL adr;
  public String key;
}

答案 1

如果一个类没有在代码中显式定义a,它将自动生成,并且不能保证不同的机器会生成相同的id;看起来这正是所发生的事情。此外,如果类在任何方面都不同(使用不同版本的类),则自动生成的 s 也将不同。private static final long serialVersionUIDserialVersionUID

从界面的文档Serializable

如果可序列化类未显式声明 ,则序列化运行时将根据类的各个方面计算该类的默认值,如 Java(TM) 对象序列化规范中所述。但是,强烈建议所有可序列化的类显式声明值,因为默认计算对类详细信息高度敏感,这些类详细信息可能因编译器实现而异,因此可能导致在反序列化期间出现意外情况。因此,为了保证不同 Java 编译器实现之间的值一致,可序列化类必须声明显式值。还强烈建议显式声明尽可能使用修饰符,因为此类声明仅适用于立即声明的类 - 字段作为继承成员没有用处。数组类不能声明显式 ,因此它们始终具有默认的计算值,但对于数组类,匹配值的要求是免除的。serialVersionUIDserialVersionUIDserialVersionUIDserialVersionUIDInvalidClassExceptionsserialVersionUIDserialVersionUIDserialVersionUIDprivateserialVersionUIDserialVersionUIDserialVersionUID

您应该在类定义中定义一个,例如:serialVersionUID

class MyClass implements Serializable {
    private static final long serialVersionUID = 6529685098267757690L;
    ...

答案 2

可能发生的一件事:

  • 1:使用给定库 A(版本 X)创建序列化数据
  • 2:然后尝试使用相同的库 A(但版本 Y)读取此数据

因此,在编译时,对于版本 X,JVM 将生成第一个串行 ID(对于版本 X),并且它将对另一个版本 Y(另一个串行 ID)执行相同的操作。

当程序尝试反序列化数据时,它不能,因为这两个类不具有相同的串行 ID,并且程序不能保证两个序列化对象对应于相同的类格式。

假设您在此期间更改了构造函数,这对您来说应该是有意义的。