transient, 译作“短暂的,临时的”,他是 java 关键字之一,只能修饰变量,被修饰的实例变量,在对象存储时,它将不再需要维持。

示例

这里,我们可以简单地理解为,对一个对象的变量做临时处理,使其只能存在于内存中,而对对象进行文件的读写,或者网络传输时,被修饰的属性的值为 null。
下面,结合实例分析一下:

User.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
37
38
39
40
/*
* user实体类
*/
class User implements Serializable {
private static final long serialVersionUID = 1L;

private String username;
private String password;

public User() {
// TODO Auto-generated constructor stub
}

public User(String username, String password) {
super();
this.username = username;
this.password = password;
}

public String getUsername() {
return username;
}

public void setUsername(String username) {
this.username = username;
}

public String getPassword() {
return password;
}

public void setPassword(String password) {
this.password = password;
}

@Override
public String toString() {
return "User [username=" + username + ", password=" + password + "]";
}
}

User1.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
37
38
39
40
41
42
43
/*
* User1 实体类, 其中的 password 变量被 transient 修饰
*/
public class User1 implements Serializable {

private static final long serialVersionUID = 1L;

private String username;
private transient String password;

public User1() {
super();
// TODO Auto-generated constructor stub
}

public User1(String username, String password) {
super();
this.username = username;
this.password = password;
}

public String getUsername() {
return username;
}

public void setUsername(String username) {
this.username = username;
}

public String getPassword() {
return password;
}

public void setPassword(String password) {
this.password = password;
}

@Override
public String toString() {
return "User1 [username=" + username + ", password=" + password + "]";
}

}

之后,我们执行下面的 Main 主函数

1
2
3
4
5
6
7
8
9
10
11
12
public class Main {
public static void main(String[] args) {
String username = "admin";
String password = "123456";

User user = new User(username, password);
User1 user1 = new User1(username, password);

System.out.println(user.toString());
System.out.println(user1.toString());
}
}

但是输出的结果却是:

http://cdn.xdbin.com/pics/20180609183157

User1 还是把 password 输出了,这是因为当前的User, User1的对象都没有进行序列化,所以就没有反序列化啦,这个关键字当然也就没有什么用了,
那好,我们就试着模拟一下对象的序列化(文件的读写操作)

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
// 文件读写类
public class FileIO {

File file;

public FileIO(String filepath) {
file = new File(filepath);
if (!file.exists()) {
try {
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
}

public void write(Serializable user) {
try {
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(file));
out.writeObject(user);
out.flush();
out.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}

public String read() {
String result = null;
try {
ObjectInputStream in = new ObjectInputStream(new FileInputStream(file));
Object obj = in.readObject();
result = obj.toString();
in.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return result;
}
}

接下来我们再对 Main 主函数进行修改:

1
2
3
4
5
6
7
8
9
10
11
public class Main {
public static void main(String[] args) {
//...
//加入以下代码
FileIO io = new FileIO("D:/transient.txt");
io.write(user);
System.out.println(io.read());
io.write(user1);
System.out.println(io.read());
}
}

http://cdn.xdbin.com/pics/20180609183249

这时候,密码已经成为了 null.

总结

  1. 一旦变量被transient修饰,变量将不再是对象持久化的一部分,该变量内容在序列化后无法获得访问。
  2. transient关键字只能修饰变量,而不能修饰方法和类。注意,本地变量是不能被transient关键字修饰的。变量如果是用户自定义类变量,则该类需要实现Serializable接口。
  3. 被transient关键字修饰的变量不再能被序列化,一个静态变量不管是否被transient修饰,均不能被序列化。