摘要:由以上結果分析可知,靜態變量不能被序列化,示例讀取出來的是在內存中存儲的值。關鍵字總結修飾的變量不能被序列化只作用于實現接口只能用來修飾普通成員變量字段不管有沒有修飾,靜態變量都不能被序列化好了,棧長花了半天時間,終于整理完了。
先解釋下什么是序列化
我們的對象并不只是存在內存中,還需要傳輸網絡,或者保存起來下次再加載出來用,所以需要Java序列化技術。
Java序列化技術正是將對象轉變成一串由二進制字節組成的數組,可以通過將二進制數據保存到磁盤或者傳輸網絡,磁盤或者網絡接收者可以在對象的屬類的模板上來反序列化類的對象,達到對象持久化的目的。
更多序列化請參考:《關于Java序列化你應該知道的一切》這篇文章。
什么是 transient?簡單來說就是,被 transient 修飾的變量不能被序列化。
具體來看下面的示例1
import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; /** * @author 微信公眾號:Java技術棧 */ public class TransientTest { public static void main(String[] args) throws Exception { User user = new User(); user.setUsername("Java技術棧"); user.setId("javastack"); System.out.println(" 序列化之前"); System.out.println("username: " + user.getUsername()); System.out.println("id: " + user.getId()); ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream("d:/user.txt")); os.writeObject(user); os.flush(); os.close(); ObjectInputStream is = new ObjectInputStream(new FileInputStream("d:/user.txt")); user = (User) is.readObject(); is.close(); System.out.println(" 序列化之后"); System.out.println("username: " + user.getUsername()); System.out.println("id: " + user.getId()); } } /** * @author 微信公眾號:Java技術棧 */ class User implements Serializable { private static final long serialVersionUID = 1L; private String username; private transient String id; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getId() { return id; } public void setId(String id) { this.id = id; } }
輸出結果:
序列化之前 username: Java技術棧 id: javastack 序列化之后 username: Java技術棧 id: null
示例1在 id 字段上加了 transient 關鍵字修飾,反序列化出來之后值為 null,說明了被 transient 修飾的變量不能被序列化。
靜態變量能被序列化嗎?這個話題也是最近棧長的Java技術棧vip群里面討論的,大家對這個知識點比較模糊,我就寫了這篇文章測試總結一下。
如果你也想加入我們的Java技術棧vip群和各位大牛一起討論技術,那點擊這個鏈接了解加入吧。
那么,到底靜態變量能被序列化嗎?廢話少說,先動手測試下吧!
示例2:
import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; /** * @author 微信公眾號:Java技術棧 */ public class TransientStaticTest { public static void main(String[] args) throws Exception { User2 user = new User2(); User2.username = "Java技術棧1"; user.setId("javastack"); System.out.println(" 序列化之前"); System.out.println("username: " + user.getUsername()); System.out.println("id: " + user.getId()); ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream("d:/user.txt")); os.writeObject(user); os.flush(); os.close(); // 在反序列化出來之前,改變靜態變量的值 User2.username = "Java技術棧2"; ObjectInputStream is = new ObjectInputStream(new FileInputStream("d:/user.txt")); user = (User2) is.readObject(); is.close(); System.out.println(" 序列化之后"); System.out.println("username: " + user.getUsername()); System.out.println("id: " + user.getId()); } } /** * @author 微信公眾號:Java技術棧 */ class User2 implements Serializable { private static final long serialVersionUID = 1L; public static String username; private transient String id; public String getUsername() { return username; } public String getId() { return id; } public void setId(String id) { this.id = id; } }
輸出結果:
序列化之前 username: Java技術棧1 id: javastack 序列化之后 username: Java技術棧2 id: null
示例2把 username 改為了 public static, 并在反序列化出來之前改變了靜態變量的值,結果可以看出序列化之后的值并非序列化進去時的值。
由以上結果分析可知,靜態變量不能被序列化,示例2讀取出來的是 username 在 JVM 內存中存儲的值。
transient 真不能被序列化嗎?繼續來看示例3:
import java.io.Externalizable; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInput; import java.io.ObjectInputStream; import java.io.ObjectOutput; import java.io.ObjectOutputStream; /** * @author 微信公眾號:Java技術棧 */ public class ExternalizableTest { public static void main(String[] args) throws Exception { User3 user = new User3(); user.setUsername("Java技術棧"); user.setId("javastack"); ObjectOutput objectOutput = new ObjectOutputStream(new FileOutputStream(new File("javastack"))); objectOutput.writeObject(user); ObjectInput objectInput = new ObjectInputStream(new FileInputStream(new File("javastack"))); user = (User3) objectInput.readObject(); System.out.println(user.getUsername()); System.out.println(user.getId()); objectOutput.close(); objectInput.close(); } } /** * @author 微信公眾號:Java技術棧 */ class User3 implements Externalizable { private static final long serialVersionUID = 1L; public User3() { } private String username; private transient String id; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getId() { return id; } public void setId(String id) { this.id = id; } @Override public void writeExternal(ObjectOutput objectOutput) throws IOException { objectOutput.writeObject(id); } @Override public void readExternal(ObjectInput objectInput) throws IOException, ClassNotFoundException { id = (String) objectInput.readObject(); } }
輸出結果:
null javastack
示例3的 id 被 transient 修改了,為什么還能序列化出來?那是因為 User3 實現了接口 Externalizable,而不是 Serializable。
在 Java 中有兩種實現序列化的方式,Serializable 和 Externalizable,可能大部分人只知道 Serializable 而不知道 Externalizable。
這兩種序列化方式的區別是:實現了 Serializable 接口是自動序列化的,實現 Externalizable 則需要手動序列化,通過 writeExternal 和 readExternal 方法手動進行,這也是為什么上面的 username 為 null 的原因了。
transient 關鍵字總結1)transient修飾的變量不能被序列化;
2)transient只作用于實現 Serializable 接口;
3)transient只能用來修飾普通成員變量字段;
4)不管有沒有 transient 修飾,靜態變量都不能被序列化;
好了,棧長花了半天時間,終于整理完了。如果對你有幫助,那就轉發分享一下吧!如果你也想加入我們的Java技術棧vip群和各位大牛一起討論技術,那點擊這個鏈接了解加入吧
另外,棧長已經整理了大量 Java 系列核心技術知識點文章,關注Java技術棧微信公眾號,在后臺回復關鍵字:java,即可獲取最新版。
本文原創首發于微信公眾號:Java技術棧(id:javastack),關注公眾號在后臺回復 "java" 可獲取更多,轉載請原樣保留本信息。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/73573.html
摘要:為什么叫重入鎖呢,我們把它拆開來看就明了了。釋放鎖,每次鎖持有者數量遞減,直到為止。 相信大家在工作或者面試過程中經常聽到重入鎖這個概念,或者與關鍵字 synchrozied 的對比,棧長面試了這么多人,80%的面試者都沒有答對或沒有答到點上,或者把雙重效驗鎖搞混了,哭笑不得。。 那么你對重入鎖了解有多少呢?今天,棧長幫大家撕開重入鎖的面紗,來見識下重入鎖的真實容顏。。 什么是重入鎖 ...
摘要:記得幾年前有一次棧長去面試,問到了這么一個問題中的對象都是在堆中分配嗎說明為什么當時我被問得一臉蒙逼,瞬間被秒殺得體無完膚,當時我壓根就不知道他在考什么知識點,難道對象不是在堆中分配嗎最后就沒然后了,回去等通知了。。 記得幾年前有一次棧長去面試,問到了這么一個問題: Java中的對象都是在堆中分配嗎?說明為什么! 當時我被問得一臉蒙逼,瞬間被秒殺得體無完膚,當時我壓根就不知道他在考什么...
摘要:加載因子是哈希表在其容量自動增加之前可以達到多滿的一種尺度。當哈希表中的條目數超出了加載因子與當前容量的乘積時,則要對該哈希表進行操作即重建內部數據結構,從而哈希表將具有大約兩倍的桶數。 showImg(https://upload-images.jianshu.io/upload_images/4565148-98b22ba5ae7d9723.jpg?imageMogr2/auto-...
摘要:曾幾何時,閉包好像就是一個十分難以捉摸透的東西,看了很多文章,對閉包都各有說法,以致讓我十分暈,什么內部變量外部變量的,而且大多數都只描述一個過程,沒有給閉包的定義,最后,舉幾個例子,告訴你這就是閉包。 曾幾何時,閉包好像就是一個十分難以捉摸透的東西,看了很多文章,對閉包都各有說法,以致讓我十分暈,什么內部變量、外部變量的,而且大多數都只描述一個過程,沒有給閉包的定義,最后,舉幾個例子...
閱讀 712·2021-10-14 09:42
閱讀 1966·2021-09-22 15:04
閱讀 1571·2019-08-30 12:44
閱讀 2134·2019-08-29 13:29
閱讀 2730·2019-08-29 12:51
閱讀 542·2019-08-26 18:18
閱讀 698·2019-08-26 13:43
閱讀 2803·2019-08-26 13:38