关键字transient是干啥的
百度百科的解释:
Java语言的关键字,变量修饰符,如果用transient声明一个实例变量,当对象存储时,它的值不需要维持。换句话来说就是,用transient关键字标记的成员变量不参与序列化过程。
作用:
Java的serialization提供了一种持久化对象实例的机制。当持久化对象时,可能有一个特殊的对象数据成员,我们不想用serialization机制来保存它。为了在一个特定对象的一个域上关闭serialization,可以在这个域前加上关键字transient。当一个对象被序列化的时候,transient型变量的值不包括在序列化的表示中,然而非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不能被序列化,原因是它们类变量不能序列化。
原文链接: javaworld 翻译: ImportNew.com- xbing
译文链接: http://www.importnew.com/12611.html
关键字transient是干啥的的更多相关文章
- Java中的关键字 transient
先解释下Java中的对象序列化 在讨论transient之前,有必要先搞清楚Java中序列化的含义: Java中对象的序列化指的是将对象转换成以字节序列的形式来表示,这些字节序列包含了对象的数据和信息 ...
- 【转】Java中的关键字 transient
阅读目录 先解释下Java中的对象序列化 关于transient关键字 举个例子 参考资料 先解释下Java中的对象序列化 在讨论transient之前,有必要先搞清楚Java中序列化的含义: Jav ...
- 【JSON 注解】JSON循环引用2----JSON注解@JsonIgnoreProperties+JAVA关键字transient+后台对象与JSON数据的格式互相转化
接着来说这个JSON循环引用的问题: 关于JSON格式的转化,其实关键就是这几个依赖: <!-- json --> <!-- 1号 --> <dependency> ...
- Java关键字:transient,strictfp和volatile简介
关键字:transient 使用对象:字段 介绍:transient说明一个属性是临时的,不会被序列化. 当对象进行序列化(Serializable)过程时候,有一些属性的状态是瞬时的,这样的对象是无 ...
- java 关键字 transient
一个对象实现了Serilizable 接口,该对象就可以被序列化. 然而在实际开发工程中,我们会遇到,这个类的有些属性不需要序列化,比如包含用户的敏感信息(如密码),为了安全起见,不希望在网络操作(主 ...
- java关键字-transient
java语言的关键字,变量修饰符,如果用transient声明一个实例变量,当对象存储时,它的值不需要维持. Java的serialization提供了一种持久化对象实例的机制.当持久化对象时,可能有 ...
- Java关键字transient和volatile小结(转)
Java关键字transient和volatile小结(转) transient和volatile两个关键字一个用于对象序列化,一个用于线程同步,都是Java中比较高阶的话题,简单总结一下. tran ...
- java 关键字transient
http://www.cnblogs.com/lanxuezaipiao/p/3369962.html 1. transient的作用及使用方法 我们都知道一个对象只要实现了Serilizable接口 ...
- 转载:关于java关键字transient
今天在map源码中看到这个关键字 百度看一下 转载记录下 源文:http://www.cnblogs.com/lanxuezaipiao/p/3369962.html 1. transient的作 ...
随机推荐
- 爬虫实例学习——爬取酷狗TOP500数据
酷狗网址:https://www.kugou.com/yy/rank/home/1-8888.html?from=rank 环境:eclipse+pydev import requests from ...
- Codeforces 1228D. Complete Tripartite
传送门 不妨设 $1$ 号点在集合 $1$ 里 那么对于其他点,有且只有所有和 $1$ 没有边的点都在集合 $1$ 里 考虑不在集合 $1$ 的任意一个点 $x$ ,不妨设它在集合 $2$ 里 那么所 ...
- 第一章 T-SQL查询和编程基础 T-SQL语言基础(1)
T-SQL查询和编程基础(1) 1.1 理论背景 SQL是为查询和管理关系型数据库管理系统(RDBMS)中的数据而专门设计的一种标准语言. RDBMS是一种基于关系模型的数据库管理系统,关系模型则是一 ...
- java实现spark常用算子之join
import org.apache.spark.SparkConf;import org.apache.spark.api.java.JavaPairRDD;import org.apache.spa ...
- springboot配置文件之yml的语法学习
springboot配置文件(.yml/.yaml.properties) YAML(YAML Ain't Markup Language) YAML A Markup Language:是一个标记语 ...
- 01 Mysql数据库初识
一.数据库概述 1.什么是数据库? 什么是数据库呢? 先来看看百度怎么说的 数据库,简而言之可视为电子化的文件柜——存储电子文件的处所,用户可以对文件中的数据运行新增.截取.更新.删除等操作. 所谓“ ...
- python 运算符与流程控制
运算符与流程控制 运算符 赋值运算 用'='表示,'='的左边只能是变量 算术运算 +.-.*:加.减.乘 /:除法运算,运算结果为浮点数 //:除法运算,运算结果为整数(商) %:求余 **:求幂 ...
- js 数据类型的判断
1. typeof 运算符 typeof 可以判断基本数据类型: typeof 123; // "number" typeof 'abc'; // "string&quo ...
- mybatis字符#与字符$的区别
问题:使用in查询查询出一批数据,in查询的参数是字符串拼接的.调试过程中,把mybatis输出的sql复制到navicat中,在控制台将sql的参数也复制出来,替换到sql的字符 '?' 的位置,执 ...
- Linux Exploit系列之一 典型的基于堆栈的缓冲区溢出
Linux (x86) Exploit 开发系列教程之一(典型的基于堆栈的缓冲区溢出) Note:本文大部分来自于看雪hackyzh的中文翻译,加入了一些自己的理解 典型的基于堆栈的缓冲区溢出 虚拟机 ...