Java中静态反序列化的差异取决于序列化对象的时间

时间:2019-01-02 12:46:33

标签: java serialization static

我正在尝试弄清Java中的(de /)序列化。

我已经读到static变量不是 序列化的。

为弄清楚这一点,我举了一个小例子:

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 SerialDemo {

    private static void writeFile() throws IOException, ClassNotFoundException {
        ObjectOutputStream o=new ObjectOutputStream(new FileOutputStream("foo"));
        Test test = new Test();
        o.writeObject(test);
        o.flush();
    }

    private static Test readFile() throws FileNotFoundException, IOException, ClassNotFoundException {
        ObjectInputStream in=new ObjectInputStream(new FileInputStream("foo"));
        return (Test) in.readObject();
    }
}
class Test implements Serializable{
    static Integer i;
    public Test(){
        i = 10;
    }
}

为什么这两种主要方法的运行方式有所不同?

第一版: 一次运行即可序列化和反序列化

public static void main(String[] args)  {

        try {
            // Serialization
            writeFile();
            // Deserialization
            Test deserializedFile = readFile();
            System.out.println(deserializedFile.i);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

这将输出10。但为什么?我认为Integer i的值未序列化,因为它是static

第二版: 在两个不同的运行中进行序列化和反序列化。

如果我第一次跑步:

public static void main(String[] args)  {
        try {
            // Serialization
            writeFile();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

第二次运行:

public static void main(String[] args)  {
        try {
            // Deserialization
            Test deserializedFile = readFile();
            System.out.println(deserializedFile.i);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

它也会输出null,正如我在第一版中所建议的那样。

有什么区别?!

3 个答案:

答案 0 :(得分:2)

在您的第一个示例中,值10仍位于静态变量i内,因为它在同一运行中。 readFile()方法实际上并未加载它。

在第二个示例中,第一次运行中该值仍为10,但是在第二次运行中,它是默认值null(尚未调用构造函数) ,调用readFile()实际上不会将值加载到i中。


在第一个示例中,尝试在deserializedFile.i = null;之前调用readFile(),您会注意到与第二个示例中发生的行为相同。

答案 1 :(得分:2)

简单:它是一个静态变量。当您使用构造函数创建一个实例时,它将在您的第一个示例中初始化!

在第二个示例中,从未调用该构造函数,该字段保持为空!

这就是全部。正如您自己说的那样:静态字段是 not 写入该文件。在您的两个示例中,唯一重要的是一个版本调用了构造函数,而另一个版本则没有。

除此之外,这里还有另一个误解:您编写 deserializedFile.i ......从概念上来说是错误的。您应该改用 Test.i 。静态变量对于所有实例都是相同的,它们的作用域是Test类,而不是该类的某些实例!

仅作记录: deserializedFile 是一个非常令人误解的名称。该变量表示反序列化的Test对象。对文件不是不是!名字应该说出他们的意思,而不是说谎。这个名字很重要!

答案 2 :(得分:1)

它按预期工作。在第一次运行时, i 变量未序列化。您将看到在 Test 构造函数中设置的值,并且由于其静态值对于同一类的所有对象都是相同的。

在第二次运行中,您不会通过构造函数创建Test类,因此未设置该值。反序列化不会调用Test构造函数,也不会反序列化i值,因此您会看到正确的输出null值。