Java transient关键字

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堆中,并不会受到序列化的影响。这个是容易被忽略的坑,需要留意一下。

本文分享自微信公众号 - Android每日一讲(gh_f053f29083b9)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2018-04-05

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏CSDN技术头条

从架构角度来看 Java 分布式日志如何收集

本文来自作者 张振华 在 GitChat 上分享 「从架构角度来看 Java 分布式日志如何收集」

86650
来自专栏CSDN技术头条

常用 XML 解析技术

现在的软件项目都不是独立的一个项目,都是多系统协调工作。这样的话就涉及到系统间的通讯,通讯就会跟报文传输挂上关系。系统间使用怎样的报文格式进行通讯呢?有的使用固...

16530
来自专栏码神联盟

图像识别 | 使用 Java 实现AI人工智能技术-图像识别功能

说到语音识别、语音翻译、图像识别、人脸识别等等,现在已经非常非常非常普及了,看过‘最强大脑’的朋友,也应该对‘小度’这个机器人有所了解,战胜国际顶尖的‘大脑’-...

2.3K50
来自专栏CSDN技术头条

Java 并发编程之美-线程相关的基础知识

借用 Java 并发编程实践中的话:编写正确的程序并不容易,而编写正常的并发程序就更难了;相比于顺序执行的情况,多线程的线程安全问题是微妙而且出乎意料的,因为在...

21730
来自专栏BestSDK

0元买!买!买!支付平台再曝漏洞,JAVA SDK存在XXE攻击|附解决方法

国家信息安全漏洞共享平台(CNVD)收录了第三方支付平台JAVA SDK存在XXE漏洞(CNVD-2018-12508)。综合利用上述漏洞,攻击者可实现商户服务...

16230
来自专栏阮一峰的网络日志

每周分享第 11 期

6月27日,TC39 委员会正式通过了《ECMAScript 2018标准》,新增了四个较大的语法点,以及几个较小的语法点。我看了一下后面还有50多个正在排队、...

12320
来自专栏CSDN技术头条

深入理解 Java 多线程核心知识:跳槽面试必备

多线程相对于其他 Java 知识点来讲,有一定的学习门槛,并且了解起来比较费劲。在平时工作中如若使用不当会出现数据错乱、执行效率低(还不如单线程去运行)或者死锁...

12730
来自专栏码神联盟

短信 | 教你使用 JAVA实现 【短信发送】 功能

77850
来自专栏码神联盟

语音识别 | Java 实现 AI 人工智能技术 - 语音识别功能

说到语音识别、语音翻译、图像识别、人脸识别等等,现在已经非常非常非常普及了,看过‘最强大脑’的朋友,也应该对‘小度’这个机器人有所了解,战胜国际顶尖的‘大脑’-...

2.8K60
来自专栏阮一峰的网络日志

Web Worker 使用教程

JavaScript 语言采用的是单线程模型,也就是说,所有任务只能在一个线程上完成,一次只能做一件事。前面的任务没做完,后面的任务只能等着。随着电脑计算能力的...

43160

扫码关注云+社区

领取腾讯云代金券

年度创作总结 领取年终奖励