背景:聽說transient Java高階語法是挺進BAT必經之路。 transient: Java中transient 關鍵字的作用,簡單的說就是讓某些被修飾的成員屬性變數不被序列化。 這又扯到了序列化和反序列化: Java中對象的序列化是指將對象轉換成以位元組序列的形式來表示,這些位元組序列包含了對 ...
背景:聽說transient Java高階語法是挺進BAT必經之路。
transient:
Java中transient 關鍵字的作用,簡單的說就是讓某些被修飾的成員屬性變數不被序列化。
這又扯到了序列化和反序列化:
Java中對象的序列化是指將對象轉換成以位元組序列的形式來表示,這些位元組序列包含了對象的數據和信息,一個序列化後的對象可以被寫到資料庫或文件中,也可以用網路傳輸;就比如我們使用緩存cache/redis或遠程調用RPC(網路傳輸)如一些密碼等不想讓人看到的敏感信息的時候,都要讓緩存或傳輸的實體類實現Serializable介面,就是為了序列化實體類。 反序列化:序列化後的終極目的還是反序列化,恢複原先的Java對象,So序列化後的總結序列都是可以恢復為java對象的,此恢復過程就稱為反序列化。
具體來說:
1、transient修飾的變數將不再是對象持久化的一部分,此變數內容在序列化後無法獲得;
2、transient關鍵字只能修飾變數,本地變數除外,而不能修飾方法和類;
3、transient修飾的變數不能再被序列化,除此之外靜態變數有無transient修飾都不能被序列化;
如下情況可以考慮使用transient關鍵字修飾:
1、類中的某個欄位可以根據其他的欄位推導出來,如一個盈利類有三個屬性(出售單價、進價、利潤),那麼在序列化的時候,利潤這個屬性就沒必要序列化了;
2、除此之外,具體看項目的業務需求,哪些欄位不想被序列化則用transient 修飾即可;
另外:不序列化還有一個好處,那就是節省記憶體空間。
寫個例子驗證下:一個實體類讀寫流的操作,password用transient修飾,age用static修飾,userName常規操作,序列化實體類執行發現,password無法序列化,age結果值和反序列化之前不一致。
FYI:
1 import java.io.ByteArrayInputStream;
2 import java.io.ByteArrayOutputStream;
3 import java.io.ObjectInputStream;
4 import java.io.ObjectOutputStream;
5 import java.io.Serializable;
6 import lombok.Data;
7 import lombok.extern.slf4j.Slf4j;
8
9 @Slf4j
10 public class TestTransient {
11 public static void main(String[] args) throws Exception {
12 TestTransient.transientTest("tjt", "password666", 22);
13 }
14 public static void transientTest(String userName, String password,Integer age) throws Exception {
15 Account account = new Account();
16 account.setUserName(userName);
17 account.setPassword(password);
18 account.setAge(age);
19 log.info("before serializeble result is:"+account.getUserName()+"-"+account.getPassword()+"-"+account.getAge());
20 ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
21 ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
22 objectOutputStream.writeObject(account);
23 byte[] bytes = byteArrayOutputStream.toByteArray(); // 將account 轉為流
24 account.age = 18; // 在反序列化之前改變age值,結果:反序列化後的結果沒有從序列化中取age值
25 ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
26 ObjectInputStream objectInputStream = null;
27 objectInputStream = new ObjectInputStream(byteArrayInputStream);
28 Account accountAfter = (Account) objectInputStream.readObject(); // 從流中獲取account
29 log.info("after serializeble result is:"+accountAfter.getUserName()+"-"+accountAfter.getPassword()+"-"+accountAfter.getAge());
30 }
31 @Data
32 static class Account implements Serializable {
33 private static final long serialVersionUID = -8994113761711738784L;
34 private String userName;
35 private transient String password;
36 private static Integer age;
37 public static Integer getAge() {
38 return age;
39 }
40 public static void setAge(Integer age) {
41 Account.age = age;
42 }
43 }
44 }
執行結果:
- before serializeble result is:tjt-password666-22
- after serializeble result is:tjt-null-18