在我的上一篇博文中讲解了一些基本的关于java序列化与反序列化的问题,现在我们一起来对对象中声明为transient和static的变量进行解析。
1:类中声明为transient变量
一旦类中某个变量声明为transient,则会告诉JVM,你不用帮我序列化该变量,我自己来进行序列化。将数据成员声明为transient后,序列化过程就无法将其加进对象字节流中,没有从transient数据成员发送的数据。后面数据反序列化时,要重建数据成员(因为它是类定义的一部分),但不包含任何数据,因为这个数据成员不向流中写入任何数据。记住,对象流不序列化。
还是上一篇博文代码,只是name属性中多加了个static,测试大妈如下:
package com.test;
import java.io.*;
public class Person implements Serializable {
private static String name = "";//在这里和之前的有变动,多了个static
public Person(){
name = "高中同学都叫我ROBIN";
}
public Person(String name){
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public static void main(String[] args) {
Person person =new Person();
//File file = new File("H:\\test.txt");//建议用File.separator
try {
FileOutputStream fos = new FileOutputStream("test.out");//暂存内容
ObjectOutputStream oos = new ObjectOutputStream(fos);
System.out.println(" 1> " + person.getName());
person.setName("我为自己代言!!!");
oos.writeObject(person);
oos.close();
} catch (Exception ex) { ex.printStackTrace(); }
try {
FileInputStream fis = new FileInputStream("test.out");
ObjectInputStream ois = new ObjectInputStream(fis);
person = (Person) ois.readObject();
System.out.println(" 2> " + person.getName());
ois.close();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
测试结果如下:
我上面不是说了吗static变量是不能狗被序列化的,按道理反序列化中调用getName方法输出结果应该也是和第一句话一样的啊!这到底是怎么了,难道我说的不对,看编译出的结果我也纳闷了,后来我在网上查了下,有一个答案解决了我的谜底:
那就是静态成员属于类级别的,所以不能序列化,这个之前我们都知道了。这里的不能序列化的意思,是序列化信息中不包含这个静态成员域为什么测试成功,是因为我是在同一个机器(而且是同一个进程),因为我的jvm已经把name变量加载进来了,所以我获取的是加载好的name,如果我把该变量传到另一台机器别的机器是不能狗得到后一个设置name值的,也就是图片中的第二个值而是两个值一样。
但也有些学过c++或则java的人会说,静态变量虽然术语类的,那为什么c++或则中还可以用对象.方法进行调用,虽然可以但程序还是会转换成进行类名.方法进行调用,而我序列化是序列化对象,所以跟说明了static不能狗被序列化缘由。
至于transient原理是和static一样的,就不多说了。