Java transient关键字解析

本文内容很简单,但是因为transient这个关键字平时用得很少,我担心过段时间又不知道它是干嘛的了,写出来最起码可以让记忆更深刻,所以写本文的目的就是备忘!老鸟就不用往下看了~

前言

在进入正文之前,我们先来看一段很简单的代码:
Account.java:

     
     
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
     
     
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

     
     
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
     
     
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关键字:

     
     
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
     
     
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变量根本不属于任何对象。


转载:http://qifuguang.me/2016/06/24/Java-transient%E5%85%B3%E9%94%AE%E5%AD%97%E8%A7%A3%E6%9E%90/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值