transient關鍵字詳解transient關鍵字詳解


1:用途:
我們知道,當一個對象實現了Serilizable接口,這個對象就可以被序列化,我們不關心其內在的原理,只需要了解這個類實現了Serilizable接口,這個類的所有屬性和方法都會自動序列化。而在開發過程中,我們可能要求:當對象被序列化時(寫入字節序列到目標文件)時,有些屬性需要序列化,而其他屬性不需要被序列化,打個比方,如果一個用戶有一些敏感信息(如密碼,銀行卡號等),為了安全起見,不希望在網絡操作(主要涉及到序列化操作,本地序列化緩存也適用)中被傳輸,這些信息對應的變量就可以加上transient關鍵字。換句話說,這個字段的生命周期僅存於調用者的內存中而不會寫到磁盤里持久化。
所以,transient的用途在於:阻止實例中那些用此關鍵字聲明的變量持久化;當對象被反序列化時(從源文件讀取字節序列進行重構),這樣的實例變量值不會被持久化和恢復。例如,當反序列化對象——數據流(例如,文件)可能不存在時,原因是你的對象中存在類型為java.io.InputStream的變量,序列化時這些變量引用的輸入流無法被打開。

2:使用方法:
序列化的時候,將不需要序列化的屬性前添加關鍵字transient即可。
示例:

 1 package com.springboot.study.tests;
 2 
 3 import lombok.Data;
 4 
 5 import java.io.*;
 6 
 7 /**
 8  * @Author: guodong
 9  * @Date: 2021/2/4 10:38
10  * @Version: 1.0
11  * @Description:
12  */
13 public class TestTransient {
14 
15     public static void main(String[] args) {
16         UserInfo userInfo = new UserInfo("張三", "123456");
17         System.out.println(userInfo);
18         try {
19             // 序列化,被設置為transient的屬性沒有被序列化
20             ObjectOutputStream o = new ObjectOutputStream(new FileOutputStream("UserInfo.txt"));
21             o.writeObject(userInfo);
22             o.close();
23         } catch (Exception e) {
24             // TODO: handle exception
25             e.printStackTrace();
26         }
27 
28         try {
29             // 重新讀取內容
30             ObjectInputStream in = new ObjectInputStream(new FileInputStream("UserInfo.txt"));
31             UserInfo readUserInfo = (UserInfo) in.readObject();
32             //讀取后psw的內容為null
33             System.out.println(readUserInfo.toString());
34         } catch (Exception e) {
35             // TODO: handle exception
36             e.printStackTrace();
37         }
38     }
39 
40 }
41 
42 
43 @Data
44 class UserInfo implements Serializable {
45 
46     private static final long serialVersionUID = 996890129747019948L;
47 
48     private String name;
49 
50     private transient String psw;
51 
52     public UserInfo(String name, String psw) {
53         this.name = name;
54         this.psw = psw;
55     }
56 
57     public String toString() {
58         return "name=" + name + ", psw=" + psw;
59     }
60 
61 }

運行結果如下圖所示:

name=張三, psw=123456
name=張三, psw=null

密碼字段為null,說明被標記為transient的屬性在對象被序列化的時候不會被保存。

使用小結:
1,一旦變量被transient修飾,變量將不再是對象持久化的一部分,該變量內容在序列化后無法獲得訪問。
2,transient關鍵字只能修飾變量,而不能修飾方法和類。注意,本地變量是不能被transient關鍵字修飾的。變量如果是用戶自定義類變量,則該類需要實現Serializable接口。
3,被transient關鍵字修飾的變量不再能被序列化,一個靜態變量不管是否被transient修飾,均不能被序列化。
對於第三點,加上static之后,依然能把姓名輸出。這是因為:反序列化后類中static型變量name的值為當前JVM中對應static變量的值,這個值是JVM中的不是反序列化得出的。下例可說明,其值時JVM中得到的而不是反序列化得到的:

 1 package com.springboot.study.tests;
 2 
 3 import lombok.AllArgsConstructor;
 4 import lombok.Data;
 5 import lombok.NoArgsConstructor;
 6 import lombok.ToString;
 7 
 8 import java.io.*;
 9 
10 /**
11  * @Author: guodong
12  * @Date: 2021/2/4 10:38
13  * @Version: 1.0
14  * @Description:
15  */
16 @Data
17 @NoArgsConstructor
18 @AllArgsConstructor
19 class UserInfo implements Serializable {
20     private static final long serialVersionUID = 996890129747019948L;
21     private static String name;
22     private transient String psw;
23 
24     public static String getName() {
25         return name;
26     }
27 
28     public static void setName(String name) {
29         UserInfo.name = name;
30     }
31 
32     public void setPsw(String psw) {
33         this.psw = psw;
34     }
35 
36     @Override
37     public String toString() {
38         return "name=" + name + ", psw=" + psw;
39     }
40 }
41 
42 
43 public class TestTransient {
44     public static void main(String[] args) {
45         UserInfo userInfo = new UserInfo();
46         userInfo.setPsw("25657");
47         userInfo.setName("張6三");
48         System.out.println(userInfo);
49         try {
50             // 序列化,被設置為transient的屬性沒有被序列化
51             ObjectOutputStream o = new ObjectOutputStream(new FileOutputStream("UserInfo.txt"));
52             o.writeObject(userInfo);
53             o.close();
54         } catch (Exception e) {
55             // TODO: handle exception
56             e.printStackTrace();
57         }
58         try {
59             //在反序列化之前改變name的值
60             userInfo.setName("hello");
61             // 重新讀取內容
62             ObjectInputStream in = new ObjectInputStream(new FileInputStream("UserInfo.txt"));
63             UserInfo readUserInfo = (UserInfo) in.readObject();
64             //讀取后psw的內容為null
65             System.out.println(readUserInfo.toString());
66         } catch (Exception e) {
67             // TODO: handle exception
68             e.printStackTrace();
69         }
70     }
71 
72 }

運行結果如下所示:

name=張6三, psw=25657
name=hello, psw=null

這說明反序列化后類中static型變量name的值為當前JVM中對應static變量的值,為修改后hello,而不是序列化時的值“張6三”,也就是說靜態變量是無法進行序列化的,在反序列前如果修改對象的值(靜態變量的值),則打印結果會變成修改后的值,那序列化就沒有意義了,所以注意一下,靜態變量無法序列化。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM