Java transient关键字解析
2017-05-12 13:26
316 查看
本文内容很简单,但是因为
Account.java:
TransientTest.java
上面的代码很简单,大概的逻辑就是:
先创建一个Account对象(实现了Serializable接口),这个对象有两个属性:用户名和密码,然后将改对象序列化写到文件,最后再从文件反序列化回来,前后两次打印account的信息,做一个对比。
很显然,上面这段代码的执行结果如下:
原始数据:
userId: winwill2012
password: 168
从文件恢复:
userId: winwill2012
password: 168
Process finished with exit code 0
看起来一切都很正常。对,上面的代码没有任何问题。
然而,本文讨论的重点是Java中用得并不是很多(博主工作三年多,在实际生产过程中一次没用到)的
然后再次执行上面的代码,得到的结果如下:
原始数据:
userId: winwill2012
password: 168
从文件恢复:
userId: winwill2012
password: null
Process finished with exit code 0
看到了什么?!!!该死的,我的密码丢了!!
我们要在网络上传输一些客户的资料,但是对于非常敏感的数据(比如薪资,各类密码之类的),我们担心在传输过程中这些敏感数据被窃取。
在上面这样的场景下,
我们知道在Java中要想让一个类能够实现序列化,可以通过如下两种方法:
实现Serializable接口,这种情况下,对象的序列化和反序列化都是java自己的机制自动实现的,不需要人为实现;
实现Externalizable接口,可以实现writeExternal()和readExternal()这两个方法,完成自己的序列化/反序列化操作;
transient修饰的属性不能被序列化这句话只在上面的第一种情况下成立,为什么呢?
因为 如果实现的是Externalizable接口,序列化和反序列化都是自己控制的,不受
transient这个关键字平时用得很少,我担心过段时间又不知道它是干嘛的了,写出来最起码可以让记忆更深刻,所以写本文的目的就是备忘!老鸟就不用往下看了~
前言
在进入正文之前,我们先来看一段很简单的代码:Account.java:
package com.winwill.simple.test; import java.io.Serializable; /** * @author qifuguang * @date 16-6-23 */ public class Account implements Serializable { private String userId; private String password; public Account(String userId, String password) { this.userId = userId; this.password = password; } public String getPassword() { return password; } public String getUserId() { return userId; } public void setUserId(String userId) { this.userId = userId; } public void setPassword(String password) { this.password = password; } }
TransientTest.java
package com.winwill.simple.test; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; /** * @author qifuguang * @date 16-6-23 */ public class TransientTest { private static final String ACCOUNT_SERIALIZE_FILE_PATH = "/home/winwill2012/account"; public static void main(String[] args) throws IOException, ClassNotFoundException { Account account = new Account("winwill2012", "168"); System.out.println("原始数据:"); System.out.println("userId: " + account.getUserId()); System.out.println("password: " + account.getPassword()); ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream(ACCOUNT_SERIALIZE_FILE_PATH)); os.writeObject(account); os.flush(); os.close(); ObjectInputStream is = new ObjectInputStream(new FileInputStream(ACCOUNT_SERIALIZE_FILE_PATH)); Account recoverAccount = (Account) is.readObject(); is.close(); System.out.println("从文件恢复:"); System.out.println("userId: " + recoverAccount.getUserId()); System.out.println("password: " + recoverAccount.getPassword()); } }
上面的代码很简单,大概的逻辑就是:
先创建一个Account对象(实现了Serializable接口),这个对象有两个属性:用户名和密码,然后将改对象序列化写到文件,最后再从文件反序列化回来,前后两次打印account的信息,做一个对比。
很显然,上面这段代码的执行结果如下:
原始数据:
userId: winwill2012
password: 168
从文件恢复:
userId: winwill2012
password: 168
Process finished with exit code 0
看起来一切都很正常。对,上面的代码没有任何问题。
然而,本文讨论的重点是Java中用得并不是很多(博主工作三年多,在实际生产过程中一次没用到)的
transient关键字。
transient是干什么用的呢?先别急,我们修改一下上面的代码,在Account类的password属性前面加上
transient关键字:
package com.winwill.simple.test; import java.io.Serializable; /** * @author qifuguang * @date 16-6-23 */ public class Account implements Serializable { private String userId; private transient String password; // 就修改了这行代码 public Account(String userId, String password) { this.userId = userId; this.password = password; } public String getPassword() { return password; } public String getUserId() { return userId; } public void setUserId(String userId) { this.userId = userId; } public void setPassword(String password) { this.password = password; } }
然后再次执行上面的代码,得到的结果如下:
原始数据:
userId: winwill2012
password: 168
从文件恢复:
userId: winwill2012
password: null
Process finished with exit code 0
看到了什么?!!!该死的,我的密码丢了!!
正文
通过上面的示例,大家也许已经知道transient的作用是什么了。没错,它的作用就是阻止它所修饰的属性被序列化。为什么会有这样的需求呢?比如:
我们要在网络上传输一些客户的资料,但是对于非常敏感的数据(比如薪资,各类密码之类的),我们担心在传输过程中这些敏感数据被窃取。
在上面这样的场景下,
transient就能配上用场了, transient修饰的属性不能被序列化,但是这是有前提条件的。
我们知道在Java中要想让一个类能够实现序列化,可以通过如下两种方法:
实现Serializable接口,这种情况下,对象的序列化和反序列化都是java自己的机制自动实现的,不需要人为实现;
实现Externalizable接口,可以实现writeExternal()和readExternal()这两个方法,完成自己的序列化/反序列化操作;
transient修饰的属性不能被序列化这句话只在上面的第一种情况下成立,为什么呢?
因为 如果实现的是Externalizable接口,序列化和反序列化都是自己控制的,不受
transient的约束。
结语
竟然说到序列化,那就顺便提一下,如果一个变量是static的,那么无论是否有
transient修饰词,都不能够别序列化,因为序列化是序列化一个对象,
static变量根本不属于任何对象。
相关文章推荐
- java关键字之transient和volatile解析
- Java之transient关键字解析
- Java中Transient (用于将相关字段不被Serialized)关键字解析(转)
- Java transient关键字解析
- Java中的transient,volatile和strictfp关键字
- Java关键字之native,strictfp,transient,volatile
- java关键字Transient
- Java中的transient,volatile和strictfp关键字
- Java关键字之native,strictfp,transient,volatile
- Java中对象的串行化(Serialization)和transient关键字
- Java中的transient、volatile、strictfp关键字使用
- Java中对象的串行化(Serialization)和transient关键字
- Java语言中关键字讲解(二)transient的用途
- java串行化——Java中对象的串行化(Serialization)和transient关键字
- JAVA transient 关键字
- Java关键字之native,strictfp,transient,volatile
- java中的volatile和transient关键字
- Java中对象的串行化(Serialization)和transient关键字
- Java不常用的关键字介绍 native,strictfp,transient,volatile
- Java中对象的串行化(Serialization)和transient关键字