2019独角兽企业重金招聘Python工程师标准>>>

Java语言的transient不像class、synchronized和其他熟悉的关键字那样众所周知,因而它会出现在一些面试题中。这篇文章我将为大家讲解transient。

transient的用途

Q:transient关键字能实现什么?

A:当对象被序列化时(写入字节序列到目标文件)时,transient阻止实例中那些用此关键字声明的变量持久化;当对象被反序列化时(从源文件读取字节序列进行重构),这样的实例变量值不会被持久化和恢复。例如,当反序列化对象——数据流(例如,文件)可能不存在时,原因是你的对象中存在类型为java.io.InputStream的变量,序列化时这些变量引用的输入流无法被打开。

transient使用介绍

Q:如何使用transient?

A:包含实例变量声明中的transient修饰符。片段1提供了小的演示。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
class ClassLib implements Serializable {
     private transient InputStream is;
     private int majorVer;
     private int minorVer;
     ClassLib(InputStream is) throws IOException {
         System.out.println( "ClassLib(InputStream) called" );
         this .is = is;
         DataInputStream dis;
         if (is instanceof DataInputStream)
             dis = (DataInputStream) is;
         else
             dis = new DataInputStream(is);
         if (dis.readInt() != 0xcafebabe )
             throw new IOException( "not a .class file" );
         minorVer = dis.readShort();
         majorVer = dis.readShort();
     }
     int getMajorVer() {
         return majorVer;
     }
     int getMinorVer() {
         return minorVer;
     }
     void showIS() {
         System.out.println(is);
     }
}
public class TransDemo {
     public static void main(String[] args) throws IOException {
         if (args.length != 1 ) {
             System.err.println( "usage: java TransDemo classfile" );
             return ;
         }
         ClassLib cl = new ClassLib( new FileInputStream(args[ 0 ]));
         System.out.printf( "Minor version number: %d%n" , cl.getMinorVer());
         System.out.printf( "Major version number: %d%n" , cl.getMajorVer());
         cl.showIS();
         try (FileOutputStream fos = new FileOutputStream( "x.ser" );
                 ObjectOutputStream oos = new ObjectOutputStream(fos)) {
             oos.writeObject(cl);
         }
         cl = null ;
         try (FileInputStream fis = new FileInputStream( "x.ser" );
                 ObjectInputStream ois = new ObjectInputStream(fis)) {
             System.out.println();
             cl = (ClassLib) ois.readObject();
             System.out.printf( "Minor version number: %d%n" , cl.getMinorVer());
             System.out.printf( "Major version number: %d%n" , cl.getMajorVer());
             cl.showIS();
         } catch (ClassNotFoundException cnfe) {
             System.err.println(cnfe.getMessage());
         }
     }
}

片段1:序列化和反序列化ClassLib对象

片段1中声明ClassLib和TransDemo类。ClassLib是一个读取Java类文件的库,并且实现了 java.io.Serializable接口,从而这些实例能被序列化和反序列化。TransDemo是一个用来序列化和反序列化ClassLib实例 的应用类。

ClassLib声明它的实例变量为transient,原因是它可以毫无意义的序列化一个输入流(像上面讲述的那样)。事实上,如果此变量不是 transient的话,当反序列化x.ser的内容时,则会抛出java.io.NotSerializableException,原因是 InputStream没有实现Serializable接口。

编译片段1:javac TransDemo.java;带一个参数TransDemo.class运行应用:java TransDemo TransDemo.class。你或许会看到类似下面的输出:

1
2
3
4
5
6
7
8
ClassLib(InputStream) called
Minor version number: 0
Major version number: 51
java.io.FileInputStream@79f1e0e0
Minor version number: 0
Major version number: 51
null

以上输出表明:当对象被重构时,没有构造方法调用。此外,is假定默认为null,相比较,当ClassLib对象序列化时,majorVer和minorVer是有值的。

类中的成员变量和transient

Q:类中的成员变量中可以使用transient吗?

A:问题答案请看片段2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public class TransDemo {
     public static void main(String[] args) throws IOException {
         Foo foo = new Foo();
         System.out.printf( "w: %d%n" , Foo.w);
         System.out.printf( "x: %d%n" , Foo.x);
         System.out.printf( "y: %d%n" , foo.y);
         System.out.printf( "z: %d%n" , foo.z);
         try (FileOutputStream fos = new FileOutputStream( "x.ser" );
                 ObjectOutputStream oos = new ObjectOutputStream(fos)) {
             oos.writeObject(foo);
         }
         foo = null ;
         try (FileInputStream fis = new FileInputStream( "x.ser" );
                 ObjectInputStream ois = new ObjectInputStream(fis)) {
             System.out.println();
             foo = (Foo) ois.readObject();
             System.out.printf( "w: %d%n" , Foo.w);
             System.out.printf( "x: %d%n" , Foo.x);
             System.out.printf( "y: %d%n" , foo.y);
             System.out.printf( "z: %d%n" , foo.z);
         } catch (ClassNotFoundException cnfe) {
             System.err.println(cnfe.getMessage());
         }
     }
}

片段2:序列化和反序列化Foo对象

片段2有点类似片段1。但不同的是,序列化和反序列化的是Foo对象,而不是ClassLib。此外,Foo包含一对变量,w和x,以及实例变量y和z。

编译片段2(javac TransDemo.java)并运行应用(java TransDemo)。你可以看到如下输出:

1
2
3
4
5
6
7
8
9
w: 1
x: 2
y: 3
z: 4
w: 1
x: 2
y: 3
z: 0

这个输出告诉我们,实例变量y是被序列化的,z却没有,它被标记transient。但是,当Foo被序列化时,它并没有告诉我们,是否变量w和x被序列化和反序列化,是否只是以普通类初始化方式初始。对于答案,我们需要查看x.ser的内容。

下面显示x.ser十六进制:

1
2
00000000 AC ED 00 05 73 72 00 03 46 6F 6F FC 7A 5D 82 1D ....sr..Foo.z]..
00000010 D2 9D 3F 02 00 01 49 00 01 79 78 70 00 00 00 03 ..?...I..yxp....

由于JavaWorld中的“The Java serialization algorithm revealed”这篇文章,我们发现输出的含义:

  • AC ED 序列化协议标识

  • 00 05 流版本号

  • 73 表示这是一个新对象

  • 72 表示这是一个新的类

  • 00 03 表示类名长度(3)

  • 46 6F 6F 表示类名(Foo)

  • FC 7A 5D 82 1D D2 9D 3F 表示类的串行版本标识符

  • 02 表示该对象支持序列化

  • 00 01 表示这个类的变量数量(1)

  • 49 变量类型代码 (0×49, 或I, 表示int)

  • 00 01 表示变量名长度(1)

  • 79 变量名称(y)

  • 78 表示该对象可选的数据块末端

  • 70 表示我们已经到达类层次结构的顶部

  • 00 00 00 03 表示y的值(3)

显而易见,只有实例变量y被序列化。因为z是transient,所以不能序列化。此外,即使它们标记transien,w和x不能被序列化,原因是它们类变量不能序列化。

转载于:https://my.oschina.net/u/2288146/blog/530814

在Java中如何使用transient相关推荐

  1. java transient_【转】Java中的关键字 transient

    阅读目录 先解释下Java中的对象序列化 在讨论transient之前,有必要先搞清楚Java中序列化的含义: Java中对象的序列化指的是将对象转换成以字节序列的形式来表示,这些字节序列包含了对象的 ...

  2. java中的关键字transient说明

    这个关键字的作用其实我在写java的序列化机制中曾经写过,不过那时候只是简单地认识,只要其简单的用法,没有深入的去分析.这篇文章就是去深入分析一下transient关键字. 先给出这篇文章的大致脉络 ...

  3. [转载] JAVA中transient 关键字

    参考链接: Java中的transient关键字 今天学习到对象流,序列化反序列化的时候,老师用了一个transient关键字来防止某个属性被序列化,脑子一头懵逼,于是在网上看到了找了别人的博客,也不 ...

  4. java工作笔记020---Java中的关键字 transient

    技术交流QQ群[JAVA,C,.NET,BigData,AI]:170933152 先解释下Java中的对象序列化 在讨论transient之前,有必要先搞清楚Java中序列化的含义: Java中对象 ...

  5. Java中对象的串行化(Serialization)和transient关键字

    Java中对象的串行化(Serialization)和transient关键字 前言: 该篇文章参考自网上资料,但是部分内容经过笔者更改,因此算作原创吧,原文地址: http://www.golden ...

  6. java中transient关键字使用学习

    导师让我学习序列化和反序列化的时候才意识到自己的对java中的transient关键字不熟.看了很多介绍和学习笔记之后,对transient关键字的使用做一下总结: 如果一个对象只要实现了Serili ...

  7. java中的transient关键字详解

    前言 说实话学了一段时间java的朋友对于transient这个关键字依旧很陌生基本没怎么用过,但是transient关键字在java中却起到了不可或缺的地位!如果要说讲到,我觉得最可能出现的地方是I ...

  8. Java中的transient关键字

    前言 说实话学了一段时间java的朋友对于transient这个关键字依旧很陌生基本没怎么用过,但是transient关键字在java中却起到了不可或缺的地位!如果要说讲到,我觉得最可能出现的地方是I ...

  9. Java中transient关键字的详细总结

    目录 一.概要介绍 1. 序列化 2. 为什么要用transient关键字? 3. transient的作用 二.transient使用总结 三.使用场景 一.概要介绍 本文要介绍的是Java中的tr ...

最新文章

  1. 漫画算法:如何判断链表有环?
  2. ISA2004发布应用程序服务器
  3. 最小代价(区间dp)(ybtoj)
  4. java char类型空值_展望Java的未来:空值类型
  5. MySQL索引优化分析
  6. java switch中标签重复_java程序 怎样把id相同的记录挑出来,分别存到不同的文件中,除了switch case,数据量很大,id种类很多。...
  7. 小心!!,使用缓存的陷阱
  8. 第二季-专题0-课程规划
  9. 微信配网airkiss
  10. MCE公司:Pfizer入局IDO1小分子抑制剂
  11. glsl中uniform,attribute和varying详解
  12. ISP Pipeline lens shading
  13. ovf导入虚拟服务器,云主机 导入 ovf
  14. 保姆级教程:群晖nas内网穿透之ipv6/ipv4 ddns+frp双管齐下!
  15. 北航计算机学院往年夏令营+考研面试题目汇总
  16. python计算银行余额_Python 小案例实战 —— 简易银行存取款查询系统
  17. es6 语法,在 IE 中不兼容的处理办法
  18. 【关于echarts使用所遇问题01】---- Unable to preventDefault inside passive event listener invocation
  19. (转) 值得关注的开源软件推荐
  20. java图形验证码识别-阿里云OCR(精准率50%)

热门文章

  1. Java 二次MD5 32位小写加密算法与php页面加密结果相同
  2. 企业管理软件的需求描述方法
  3. 理解 QEMU/KVM 和 Ceph(2):QEMU 的 RBD 块驱动(block driver)
  4. Eclipse里的Java EE视图在哪里?MyEclipse里的Java EE视图在哪里?MyEclipse里的MyEclipse Java Enterprise视图在哪里?(图文详解)...
  5. Oracle“死锁”模拟
  6. 解读《电力发展“十三五”规划》
  7. Java编译那些事儿【转】
  8. goaccess在定时任务中不执行的问题
  9. OSChina 周三乱弹 —— 程序员火灾逃生指南
  10. 教你打造优秀IT博文