一文搞懂transient关键字
首先上总结:
-
用transient关键字标记的成员变量不参与序列化(Serialize)过程。也就是说,当Java对象进行存储、网络传输的时候,使用transient修饰的变量不会被序列化,保存、传输的数据中不会有被修饰的变量信息。
-
静态变量不会被序列化,所以不需要加transient关键字。
1.序列化
1.1 什么是序列化
当我们将Java对象进行网络传输、保存或者在进程间进行传递的时候,需要先将对象转换为字节序列,这个过程就叫做序列化。同理,接收的时候,需要将字节序列恢复为Java对象,这个过程就叫做反序列化。
1.2 以文件存储为例实现序列化
以上就是对序列化的大致介绍,如果想稍后了解序列化,或者想直接了解transient的作用,可以直接跳到第二节。
实现序列化的方式有两种(这里使用方法1进行演示):
- 使用Serializable接口实现序列化
- 使用Externalizable接口实现序列化
首先创建一个对象实现Serializable接口。
public class User implements Serializable {
public String name;
public Integer age;
//使用基本类型或者包装类型看个人喜好,对于可能出现的null情况个人喜欢包装类
//getter and setter
}
在Test类中实现序列化与反序列化的静态方法。
public class Test {
public static void SerializeUser() throws IOException {
User user = new User();
user.setAge(11);
user.setName("小明");
//序列化到文件中
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("./tempFile"));
oos.writeObject(user);
oos.close();
System.out.println("序列化成功");
}
public static void DeSerializeUser() throws IOException, ClassNotFoundException {
File file = new File("./tempFile");
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));
User newUser = (User)ois.readObject();
System.out.println("反序列化对象成功");
System.out.println("年纪为"+newUser.getAge());
System.out.println("姓名为"+newUser.getName());
}
public static void main(String[] args) throws IOException, ClassNotFoundException {
SerializeUser();
DeSerializeUser();
}
}
结果为
2.transient关键字
2.1 添加transient关键字
我们为age属性前添加上transient关键字,序列化对象的时候,这个属性就不会被序列化。
public class User implements Serializable {
public String name;
//使用transient关键字
public transient Integer age;
//getter and setter
}
Test类还是刚才那样,我们讲User对象序列化和反序列化。结果如下。
年纪就是null,说明没有在文件中存储。
2.2 静态变量不需要加transient
前面说到静态变量不需要加transient修饰就可以不被序列化。我们尝试将age改成static并且不加transient修饰。
public class User implements Serializable {
public String name;
public static Integer age;
//getter and setter
}
运行一下Test类中main方法
为什么这里年纪又出现了呢。这里简单解释一下。由于因为静态变量在全局区,本来流里面就没有写入静态变量,我打印静态变量当然会去全局区查找,而我们的序列化是写到磁盘上的,所以JVM查找这个静态变量的值,是从全局区查找的,而不是磁盘上。
至此transient的基本用法与知识点就讲完了,欢迎大家补充。