This question already has answers here:
What is a serialVersionUID and why should I use it?
                                
                                    (26个答案)
                                
                        
                                6年前关闭。
            
                    
在我的TCP服务器-客户端实现中,我所有的数据包均来自实现Serializable的抽象基类。我将类转换为字节并通过套接字发送,接收者将这些字节反序列化并成功接收到数据包。由于我缺乏有关序列化的知识,因此我不确定这是否行得通,因为每个数据包类都有这样的警告:


  可序列化的类CreateObjectPacket没有声明类型为long的静态最终serialVersionUID字段


经过一些研究,我发现JVM使用此UID来确保反序列化成功(如果我没有记错),因此为了摆脱此警告,我让Eclipse生成默认的UID,但是即使Client与Server程序有关Packets的类完全相同,而UID在相同的类上不同。反序列化时是否会引起任何问题,还是我应该手动设置这些1,2,3 ...等UID?顺便说一句,我将输入的字节反序列化到超抽象类Packets中,这是否也是一个问题,还是应该随意将其转换为派生的Packets?

编辑:最后,我的抽象Packets类具有一个名为fromByteArray的反序列化静态方法:

public static Packets fromByteArray(byte[] arr) {

    ByteArrayInputStream bis = new ByteArrayInputStream(arr);
    ObjectInput in = null;
    try {
        in = new ObjectInputStream(bis);
        Packets o = (Packets) in.readObject();
        return o;
    } catch (IOException | ClassNotFoundException e) {
        e.printStackTrace();
    } finally {
        try {
            bis.close();
            in.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
    return null;
}

最佳答案

经过一些研究,我发现JVM使用此UID来确保反序列化成功

具体来说,它用于标识正在(反)序列化的对象的版本。当允许自动分配UID时,如果要序列化的对象的内部结构碰巧发生变化,则开发环境(IDE)应该分配一个新的UID。这使JVM能够识别是否尝试将一个对象的版本反序列化为具有相同类名的对象的不同版本。

如果您自己分配版本ID并更改对象的内部结构(即成员字段),则还应更改版本ID。这样,当类定义和尝试从磁盘/网络反序列化的对象之间的版本不匹配时,JVM就能捕获。

重新评论:
http://docs.oracle.com/javase/6/docs/platform/serialization/spec/version.html
5.6影响序列化的类型更改-兼容与不兼容更改

UID的目的是向JVM指示对象的序列化结构是否已以无法可靠地反序列化对象的任何部分的方式更改。正如我在上面所写,仅当对要序列化的对象的结构进行不兼容的更改时,才应该更改它。如果客户端和服务器上的对象均相同,则如果客户端代码和服务器代码之间的UID不匹配,则可能会反序列化对象。您可以通过不定义UID来解决此问题,但是请注意,如果将来您的对象实现发生更改,将会带来的后果。

关于java - 序列化:serialVersionUID在网络上的重要性,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/16428836/

10-10 22:20
查看更多