3

类成员(静态)不能被序列化。原因很明显——它们不被类的对象持有。由于它们与类(而不是该类的对象)相关联,因此它们与对象分开存储。

serialVersionUID被声明为实现java.io.Serializable接口的类中的静态字段,如下所示。

private static final long serialVersionUID = 1L;

它用作Serializable类中的版本控制。如果没有明确声明,JVM 将根据Serializable类的各个方面自动完成,如Java(TM) 对象序列化规范所述。

如果它没有在实现Serializable接口的类中显式声明,则可能会发出警告。

可序列化的类SomeClass没有声明static final serialVersionUID类型的字段long

即使它是序列化的static,它是序列化的还是序列化的例外?

4

4 回答 4

4

序列化是“神奇地”完成的,有很多反射,并且有各种特殊的行为——包括例如查找类的静态 serialVersionUID

于 2012-12-17T17:30:59.353 回答
2

serialVersionUID本身没有序列化。至少,与对象的其他属性不同。相反,它作为特殊“标题”的一部分被写入您的输出目标,其中包含重建正在写入的对象所需的信息。

于 2012-12-17T17:43:07.360 回答
2

让我清楚你在serialVersionUID向文件写入和读取对象时的使用。

在下面的代码中,我编写了两个函数writeObject()readObj()

writeObject()用于将对象写入文件

readObj()用于从文件中读取对象

package com.msq;

import java.io.Serializable;

public class A implements Serializable{
    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    int a;
    transient int b;

    public int getA() {
        return a;
    }
    public void setA(int a) {
        this.a = a;
    }
    public int getB() {
        return b;
    }
    public void setB(int b) {
        this.b = b;
    }
}
package com.msq;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

public class B implements Serializable {

    /**
     * 
     */
    private static final long serialVersionUID = 123L ;
    /**
     * 
     */
    String name;
    A a;

    public B() {

    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public A getA() {
        return a;
    }

    public void setA(A a) {
        this.a = a;
    }

    public static void main(String[] args) {

        //writeObject();
        readObj();
    }

    static void writeObject() {
        B b = new B();
        b.setName("Musaddique");
        A a2 = new A();
        a2.setA(5);
        a2.setB(10);
        b.setA(a2);
        ObjectOutputStream write = null;

        try {
            write = new ObjectOutputStream(new FileOutputStream(
                    "D:\\serObj.bat"));
            write.writeObject(b);
            write.flush();
            write.close();

        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    static void readObj() {
        ObjectInputStream reader = null;

        try {
            reader = new ObjectInputStream(
                    new FileInputStream("D:\\serObj.bat"));
            B b1 = (B) reader.readObject();
            System.out.println("name: "+b1.getName());
            System.out.println("value of a: "+b1.getA().getA());
            System.out.println("value of b: "+b1.getA().getB());
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

在这里,我使用serialVersionUID = 123L了 BserialVersionUID = 1L类和 A 类,还使用transient了变量 b 的关键字,以限制将 b 的值保存到文件中。

1)将数据写入文件然后读取文件,您将获得以下输出

name: Musaddique
value of a: 5
value of b: 0

你会得到 b: 0 的值,因为我们对 b 使用了瞬态。

现在进行测试尝试通过相同的调用写入对象,但是在读取更改时,您serialVersionUID = 765L将得到以下异常

java.io.InvalidClassException: com.msq.B; local class incompatible: stream classdesc serialVersionUID = 123, local class serialVersionUID = 765
    at java.io.ObjectStreamClass.initNonProxy(Unknown Source)
    at java.io.ObjectInputStream.readNonProxyDesc(Unknown Source)
    at java.io.ObjectInputStream.readClassDesc(Unknown Source)
    at java.io.ObjectInputStream.readOrdinaryObject(Unknown Source)
    at java.io.ObjectInputStream.readObject0(Unknown Source)
    at java.io.ObjectInputStream.readObject(Unknown Source)
    at com.msq.B.readObj(B.java:81)
    at com.msq.B.main(B.java:46)

serialVersionUID因此,在从文件中读取和写入对象时必须使用相同的方法。

此外,当您将类从一台机器合并到另一台机器或系统时,它在 RMI 调用中使用。

于 2015-06-30T12:18:05.440 回答
1

不要serialVersionUID将其视为被序列化的对象数据的一部分,而是将其视为类描述的一部分。与类名是序列化流的一部分的方式相同。流格式的完整详细信息记录在Grammar for the Stream Format中。

于 2012-12-17T17:46:42.430 回答