博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
java 序列化transient 关键字使用
阅读量:7158 次
发布时间:2019-06-29

本文共 5685 字,大约阅读时间需要 18 分钟。

先解释下什么是序列化

我们的对象并不只是存在内存中,还需要传输网络,或者保存起来下次再加载出来用,所以需要Java序列化技术。

Java序列化技术正是将对象转变成一串由二进制字节组成的数组,可以通过将二进制数据保存到磁盘或者传输网络,磁盘或者网络接收者可以在对象的属类的模板上来反序列化类的对象,达到对象持久化的目的。

什么是 transient?

简单来说就是,被 transient 修饰的变量不能被序列化。

具体来看下面的示例1

import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; public class TransientTest {
    public static void main(String[] args) throws Exception {
        User user = new User();         user.setUsername("hhy");         user.setId("628");         System.out.println("\n序列化之前");         System.out.println("username: " + user.getUsername());         System.out.println("id: " + user.getId());         ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream("d:/userhhy.txt"));         os.writeObject(user);         os.flush();         os.close();         ObjectInputStream is = new ObjectInputStream(new FileInputStream("d:/userhhy.txt"));         user = (User) is.readObject();         is.close();         System.out.println("\n序列化之后");         System.out.println("username: " + user.getUsername());         System.out.println("id: " + user.getId());     } } class User implements Serializable {
    private static final long serialVersionUID = 12548965125L;     private String username;     private transient String id;     public String getUsername() {
        return username;     }     public void setUsername(String username) {
        this.username = username;     }     public String getId() {
        return id;     }     public void setId(String id) {
        this.id = id;     } }

输出结果:

序列化之前 username: hhy id: 628 序列化之后 username: Java技术栈 id: null

示例1在 id 字段上加了 transient 关键字修饰,反序列化出来之后值为 null,说明了被 transient 修饰的变量不能被序列化。

静态变量能被序列化吗?

那么,到底静态变量能被序列化吗?废话少说,先动手测试下吧!

示例2:

import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; public class TransientStaticTest {
    public static void main(String[] args) throws Exception {
        User2 user = new User2();         User2.username = "hhy1";         user.setId("520");         System.out.println("\n序列化之前");         System.out.println("username: " + user.getUsername());         System.out.println("id: " + user.getId());         ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream("d:/userhhy.txt"));         os.writeObject(user);         os.flush();         os.close();         // 在反序列化出来之前,改变静态变量的值         User2.username = "hhy2";         ObjectInputStream is = new ObjectInputStream(new FileInputStream("d:/userhhy.txt"));         user = (User2) is.readObject();         is.close();         System.out.println("\n序列化之后");         System.out.println("username: " + user.getUsername());         System.out.println("id: " + user.getId());     } } class User2 implements Serializable {
    private static final long serialVersionUID = 1751297484511274L;     public static String username;     private transient String id;     public String getUsername() {
        return username;     }     public String getId() {
        return id;     }     public void setId(String id) {
        this.id = id;     } }

输出结果:

序列化之前 username: hhy1 id: 520 序列化之后 username: hhy2 id: null

示例2把 username 改为了 public static, 并在反序列化出来之前改变了静态变量的值,结果可以看出序列化之后的值并非序列化进去时的值。

由以上结果分析可知,静态变量不能被序列化,示例2读取出来的是 username 在 JVM 内存中存储的值。

transient 真不能被序列化吗?

继续来看示例3:

import java.io.Externalizable; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInput; import java.io.ObjectInputStream; import java.io.ObjectOutput; import java.io.ObjectOutputStream; public class ExternalizableTest {
    public static void main(String[] args) throws Exception {
        User3 user = new User3();         user.setUsername("hhy");         user.setId("520");         ObjectOutput objectOutput = new ObjectOutputStream(new FileOutputStream(new File("hhy")));         objectOutput.writeObject(user);         ObjectInput objectInput = new ObjectInputStream(new FileInputStream(new File("hhy")));         user = (User3) objectInput.readObject();         System.out.println(user.getUsername());         System.out.println(user.getId());         objectOutput.close();         objectInput.close();     } } /**  * @author 微信公众号:Java技术栈  */ class User3 implements Externalizable {
    private static final long serialVersionUID = 11231325464L;     public User3() {
    }     private String username;     private transient String id;     public String getUsername() {
        return username;     }     public void setUsername(String username) {
        this.username = username;     }     public String getId() {
        return id;     }     public void setId(String id) {
        this.id = id;     }     @Override     public void writeExternal(ObjectOutput objectOutput) throws IOException {
        objectOutput.writeObject(id);     }     @Override     public void readExternal(ObjectInput objectInput) throws IOException, ClassNotFoundException {
        id = (String) objectInput.readObject();     } }

输出结果:

null 520

示例3的 id 被 transient 修改了,为什么还能序列化出来?那是因为 User3 实现了接口 Externalizable,而不是 Serializable。

在 Java 中有两种实现序列化的方式,Serializable 和 Externalizable,可能大部分人只知道 Serializable 而不知道 Externalizable。

这两种序列化方式的区别是:实现了 Serializable 接口是自动序列化的,实现 Externalizable 则需要手动序列化,通过 writeExternal 和 readExternal 方法手动进行,这也是为什么上面的 username 为 null 的原因了。

transient 关键字总结

1)transient修饰的变量不能被序列化;

2)transient只作用于实现 Serializable 接口;

3)transient只能用来修饰普通成员变量字段;

4)不管有没有 transient 修饰,静态变量都不能被序列化;

转载地址:http://vurgl.baihongyu.com/

你可能感兴趣的文章
Postgresql数据类型
查看>>
django-ckeditor 使用
查看>>
布隆过滤器
查看>>
jquary
查看>>
Spring Cloud搭建微服务架构----前言
查看>>
延时任务怎么搞
查看>>
MSql中的延迟
查看>>
android tools的添加路径设置过程
查看>>
ORACLE基本知识:表分区
查看>>
Windows下Eclipse 安装 android maven插件教程
查看>>
简明vim练级攻略
查看>>
slidingmenu使用说明
查看>>
nginx配置摘要
查看>>
传输音频
查看>>
CentOS6 图形界面(gnome)安装
查看>>
CMakeLists 可以设置的参数
查看>>
Android 6.0 解决Recyclerview 在 Scrollview 中不能高度自适应问题
查看>>
WebView Cache 缓存清除
查看>>
spring boot 源码分析(九) 事件机制 之 BootstrapApplicationListener
查看>>
Android实现号码归属地查询
查看>>