我正在尝试弄清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
,正如我在第一版中所建议的那样。
有什么区别?!
答案 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值。