這個關鍵字的作用其實我在寫java的序列化機制中曾經寫過,不過那時候隻是簡單地認識,隻要其簡單的用法,沒有深入的去分析。這篇文章就是去深入分析一下transient關鍵字。
先給出這篇文章的大緻脈絡
首先,介紹了transient的基本概念和基本用法、然後,介紹深入分析一下transient關鍵字,并介紹幾個需要掌握的問題最後,來個總結
一、初識transient關鍵字
其實這個關鍵字的作用很好了解,就是簡單的一句話:将不需要序列化的屬性前添加關鍵字transient,序列化對象的時候,這個屬性就不會被序列化。
概念也很好了解,下面使用代碼去驗證一下:

然後我們在Test中去驗證一下:
從上面可以看出,在序列化SerializeUser方法中,首先建立一個序列化user類,然後将其寫入到G://Test/template路徑中。在反序列化DeSerializeUser方法中,首先建立一個File,然後讀取G://Test/template路徑中的資料。
這就是序列化和反序列化的基本實作,而且我們看一下結果,也就是被transient關鍵字修飾的age屬性是否被序列化。
從上面的這張圖可以看出,age屬性變為了0,說明被transient關鍵字修飾之後沒有被序列化。
二、深入分析transient關鍵字
為了更加深入的去分析transient關鍵字,我們需要帶着幾個問題去解讀:
(1)transient底層實作的原理是什麼?
(2)被transient關鍵字修飾過得變量真的不能被序列化嘛?
(3)靜态變量能被序列化嗎?被transient關鍵字修飾之後呢?
帶着這些問題一個一個來解決:
1、transient底層實作原理是什麼?
java的serialization提供了一個非常棒的存儲對象狀态的機制,說白了serialization就是把對象的狀态存儲到硬碟上 去,等需要的時候就可以再把它讀出來使用。有些時候像銀行卡号這些字段是不希望在網絡上傳輸的,transient的作用就是把這個字段的生命周期僅存于調用者的記憶體中而不會寫到磁盤裡持久化,意思是transient修飾的age字段,他的生命周期僅僅在記憶體中,不會被寫到磁盤中。
2、被transient關鍵字修飾過得變量真的不能被序列化嘛?
想要解決這個問題,首先還要再重提一下對象的序列化方式:
Java序列化提供兩種方式。
一種是實作Serializable接口
另一種是實作Exteranlizable接口。 需要重寫writeExternal和readExternal方法,它的效率比Serializable高一些,并且可以決定哪些屬性需要序列化(即使是transient修飾的),但是對大量對象,或者重複對象,則效率低。
從上面的這兩種序列化方式,我想你已經看到了,使用Exteranlizable接口實作序列化時,我們自己指定那些屬性是需要序列化的,即使是transient修飾的。下面就驗證一下
首先我們定義User1類:這個類是被Externalizable接口修飾的
然後我們就可以測試了
上面,代碼分了兩個方法,一個是序列化,一個是反序列化。裡面的代碼和一開始給出的差不多,隻不過,User1裡面少了age這個屬性。
然後看一下結果:
結果基本上驗證了我們的猜想,也就是說,實作了Externalizable接口,哪一個屬性被序列化使我們手動去指定的,即使是transient關鍵字修飾也不起作用。
3、靜态變量能被序列化嗎?沒被transient關鍵字修飾之後呢?
這個我可以提前先告訴結果,靜态變量是不會被序列化的,即使沒有transient關鍵字修飾。下面去驗證一下,然後再解釋原因。
首先,在User類中對age屬性添加transient關鍵字和static關鍵字修飾。
然後,在Test類中去測試
最後,測試一下,看看結果
結果已經很明顯了。現在解釋一下,為什麼會是這樣,其實在前面已經提到過了。因為靜态變量在全局區,本來流裡面就沒有寫入靜态變量,我列印靜态變量當然會去全局區查找,而我們的序列化是寫到磁盤上的,是以JVM查找這個靜态變量的值,是從全局區查找的,而不是磁盤上。user.setAge(18);年齡改成18之後,被寫到了全局區,其實就是方法區,隻不過被所有的線程共享的一塊空間。是以可以總結一句話:
靜态變量不管是不是transient關鍵字修飾,都不會被序列化
三、transient關鍵字總結
java 的transient關鍵字為我們提供了便利,你隻需要實作Serilizable接口,将不需要序列化的屬性前添加關鍵字transient,序列化對象的時候,這個屬性就不會序列化到指定的目的地中。像銀行卡、密碼等等這些資料。這個需要根據業務情況了。