首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java transient关键字

Java transient关键字

作者头像
PhoenixZheng
发布2018-08-07 16:34:57
1.7K0
发布2018-08-07 16:34:57
举报

transient关键字是开发中用的比较少的一个关键字,它在序列化和反序列化中比较重要,通常面试时会考察它的作用和它的使用场景,还有它在什么情况下会失效。

transient 的作用

作为Java基础知识的一个点,transient的作用大家都知道是用来防止属性被序列化。因此它出现的场景都会同时有 Serializable 接口。 它的使用场景比较容易理解,比方当我们在序列化并以本地文件或其他持久化数据形式存储用户资料时,像用户的密码这样的字段我们是不希望存储的,这样的字段就需要用 transient 来修饰了。 比如下面的代码

import java.io.Serializable;

public class UserBean implements Serializable {
  private String name;
  private transient String password;

  public String getName(){
    return name;
  }

  public String getPassword(){
    return password;
  }

  public void setName(String name) {
    this.name = name;
  }

  public void setPassword(String password){
    this.password = password;
  }

  public String toString() {
    return "name: " + this.name + " psw: " + this.password;
  }
}

我们定义了个UserBean类,然后再用另外一个类来持久化用户数据,观察在序列化和反序列化的过程中数据发生了什么变化。下面是主代码

import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
import java.io.FileInputStream;
import java.io.ObjectInputStream;

public class TransientDemo {

  public static void main(String[] args) {

    UserBean user = new UserBean();
    user.setName("Jackson");
    user.setPassword("password123");

    System.out.println("User: " + user.toString());

    //begin serializing
    try {
      ObjectOutputStream fos = new ObjectOutputStream(new FileOutputStream("bean.txt"));
      fos.writeObject(user);
      fos.flush();
      fos.close();
      System.out.println("local serialized done");
    } catch (Exception e) {}

    System.out.println("de-serialzing...");
     try {
       ObjectInputStream fis = new ObjectInputStream(new FileInputStream("bean.txt"));
       user = (UserBean) fis.readObject();
       fis.close();
       System.out.println("User de-serialzed: " + user.toString());
     } catch(Exception e){}
  }
}

输出

User: name: Jackson psw: password123 local serialized done de-serialzing… User de-serialzed: name: Jackson psw: null

对比 name和password字段,被 transient修饰的密码字段在序列化后就没有被持久化了。

transient的局限

transient能作用的场景只能是和 Serializable接口搭配使用,而另外一个序列化接口, Externalizable却不能对它起效。 仔细思考就明白原因,Serializable是JVM自动进行序列化的,而 Externalizable需要我们通过 readExternal和 writeExternal 两个方法自己定义序列化和反序列化的实现方式,因此即使被 transient修饰也和能否被序列化无关。

局限二, 被 static修饰的变量也不能被序列化,与是否被 transient修饰无关。 如何理解这句话呢。可以把demo中的 name改成 static来尝试下,

public class UserBean implements Serializable {
  private static String name;
  private transient String password;
public class TransientDemo {

  public static void main(String[] args) {

    UserBean user = new UserBean();
    user.setName("Jackson");
    user.setPassword("password123");

    System.out.println("User: " + user.toString());

    //begin serializing
    try {
      ObjectOutputStream fos = new ObjectOutputStream(new FileOutputStream("bean.txt"));
      fos.writeObject(user);
      fos.flush();
      fos.close();
      System.out.println("local serialized done");
    } catch (Exception e) {}

    System.out.println("de-serialzing...");
     try {
       UserBean.name = "John Doe";
       ObjectInputStream fis = new ObjectInputStream(new FileInputStream("bean.txt"));
       user = (UserBean) fis.readObject();
       fis.close();
       System.out.println("User de-serialzed: " + user.toString());
     } catch(Exception e){}
  }
}

输出

User: name: Jackson psw: password123 local serialized done de-serialzing… User de-serialzed: name: John Doe psw: null

可以看出,即使被反序列化,static变量并没有拿到序列化时的值,因为 static变量的值是保存在JVM堆中,并不会受到序列化的影响。这个是容易被忽略的坑,需要留意一下。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-04-05,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Android每日一讲 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • transient 的作用
  • transient的局限
相关产品与服务
对象存储
对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档