本文主要讲述了在序列化和反序列化过程中,静态变量和类变量的序列化规则,并附带了实验佐证。
先放结论:
Java的静态变量不会被序列化:静态变量属于类本身,而不是类的某个特定实例。即使在序列化之前修改了静态变量的值,序列化后得到的新对象的静态变量也将是类变量的初始值。
成员变量被transient标记,那它就是瞬间变量。JVM 在序列化过程中跳过瞬态变量,这意味着在序列化对象时不会存储age变量的值。反序列化对象时,瞬间变量也不会被恢复为定义类时的初始值,而是会初始化为Java类型的默认值。例如,对于int类型,这个默认值是0。
下面进行验证:
给定Student类,实现了序列化接口。成员变量age被定义为瞬间变量,初始值是11;staticCount是静态变量,初始值是1;studentId和name为普通的成员变量。
public class Student implements Serializable {
private long studentId;
private String name;
private transient int age = 11;
private static int staticCount = 1;
public Student(long studentId, String name, int age) {
super();
this.studentId = studentId;
this.name = name;
this.age = age;
System.out.println("Constructor");
}
@Override
public String toString() {
return String.format("%d - %s - %d - %d", studentId, name, age,staticCount);
}
public long getStudentId() {
return studentId;
}
public void setStudentId(long studentId) {
this.studentId = studentId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public static int getStaticCount() {
return staticCount;
}
public static void setStaticCount(int staticCount) {
Student.staticCount = staticCount;
}
}
声明一个student实例,初始化studentId、name、age,修改类变量的值,然后再进行序列化
public class BeforeSerialized {
public static void main(String[] args) {
String filePath = "students.ser";
Student student = new Student(123, "John", 22);
Student.setStaticCount(2);
try (
FileOutputStream fos = new FileOutputStream(filePath);
ObjectOutputStream outputStream = new ObjectOutputStream(fos);
) {
outputStream.writeObject(student);
} catch (IOException ex) {
System.err.println(ex);
}
}
}
反序列化得到一个新实例student。
public class AfterSerialized {
public static void main(String[] args) {
String filePath = "students.ser";
try (
FileInputStream fis = new FileInputStream(filePath);
ObjectInputStream inputStream = new ObjectInputStream(fis);
) {
Student student = (Student) inputStream.readObject();
System.out.println(student);
} catch (ClassNotFoundException ex) {
System.err.println("Class not found: " + ex);
} catch (IOException ex) {
System.err.println("IO error: " + ex);
}
}
}
打印结果如下。
studentId=123,name=John:保留了序列化前的对象的值,证明普通成员变量是可被序列化的;
age=0:没有保留序列化前的对象的age=22,也不是类定义中的age=11,而是age属于的int类型的默认值,证明瞬间变量在序列化过程中被跳过并且依据Java类型的默认值进行初始化。
staticCount=1:没有保留序列化前修改的staticCount=2,而是类定义中的staticCount=1,证明静态变量仍是静态变量的初始值。