日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

Java 序列化之 Externalizable

發布時間:2024/9/30 java 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java 序列化之 Externalizable 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

相關文章: Java 序列化 之 Serializable

JDK中除了提供 Serializable 序列化接口外,還提供了另一個序列化接口Externalizable,使用該接口之后,之前基于Serializable接口的序列化機制就將失效。Externalizable 的序列化機制優先級要高于 Serializable 。

Externalizable 源碼分析


從源碼中,我們可以看到 Externalizable 接口繼承了 Serializable 接口。并定義了兩個方法 writeExternal 和 readExternal 方法

Externalizable 示例一

User 類

public class User implements Externalizable {private static final long serialVersionUID = 1318824539146791009L;private String userName;private transient String 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;}@Overridepublic String toString() {return "User [userName=" + userName + ", password=" + password + "]";}@Overridepublic void writeExternal(ObjectOutput out) throws IOException {}@Overridepublic void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {} }

User 類有兩個屬性,一個是非 transient 字段的userName 和一個 transient 字段的password,并實現了 Externalizable 接口,writeExternal 和 readExternal 方法都不填寫任何邏輯。
然后下面的代碼,來看下序列化和反序列化 User 對象的效果。

public class Test{public static void main(String[] args) throws Exception {File file = new File("d:\\a.user");ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file));User user1 = new User();user1.setUserName("zhangsan");user1.setPassword("123456");oos.writeObject(user1);ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));User user2 = (User) ois.readObject();System.out.println(user2);} }

執行結果:
User [userName=null, password=null]

示例二

實現 Externalizable 接口的兩個方法的實現,代碼如下:

public class User implements Externalizable {private static final long serialVersionUID = 1318824539146791009L;private String userName;private transient String 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;}@Overridepublic String toString() {return "User [userName=" + userName + ", password=" + password + "]";}@Overridepublic void writeExternal(ObjectOutput out) throws IOException {out.writeObject(this.userName);out.writeObject(this.password);}@Overridepublic void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {this.userName = in.readObject().toString();this.password = in.readObject().toString();} }

在 writeExternal 方法中寫入 userName 和 password 兩個數據,在 readExternal 方法中讀取反序列化的信息并賦值給 userName 和 password 兩個字段。

執行 Test.main 方法。

執行結果如下:
User [userName=zhangsan, password=123456]

結論一

  • 實現 Externalizable 接口后,序列化的細節需要由開發人員自己實現。由于writeExternal()與readExternal()方法未作任何處理,那么該序列化行為將不會保存/讀取任何一個字段。這也就是為什么輸出結果中所有字段的值均為空。
  • 實現 Externalizable 接口后,屬性字段使用 transient 和不使用沒有任何區別。

示例三

public class User implements Serializable, Externalizable {private static final long serialVersionUID = 1318824539146791009L;private String userName;private transient String 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;}@Overridepublic String toString() {return "User [userName=" + userName + ", password=" + password + "]";}private void readObject(ObjectInputStream s) throws Exception {s.defaultReadObject();this.password = (String) s.readObject();}private void writeObject(ObjectOutputStream s) throws IOException {s.defaultWriteObject();s.writeObject("serializable:"+this.password);}@Overridepublic void writeExternal(ObjectOutput out) throws IOException {out.writeObject(this.userName);out.writeObject("externalizable:"+this.password);}@Overridepublic void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {this.userName = (String)in.readObject();this.password = (String)in.readObject();} }

User 類既實現了 Serializable 接口,又實現了 Externalizable 接口(其實沒啥意義,因為 Externalizable 已經繼承了 Serializable 接口)。
在 readObject 和 writeObject 方法中實現了序列化和發序列化。
在 readExternal 和 writeExternal 方法中也實現了序列化和發序列化。

當執行 Test.main() 方法,執行的結果如下:

User [userName=zhangsan, password=externalizable:123456]
可以看出,執行的是 Externalizable ,而不是 Serializable 。

結論二

Externalizable 序列化的優先級比Serializable的優先級高。

示例四

public class User implements Externalizable {private static final long serialVersionUID = 1318824539146791009L;private String userName;private transient String password;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;}@Overridepublic String toString() {return "User [userName=" + userName + ", password=" + password + "]";}@Overridepublic void writeExternal(ObjectOutput out) throws IOException {out.writeObject(this.userName);out.writeObject("externalizable:"+this.password);}@Overridepublic void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {this.userName = (String)in.readObject();this.password = (String)in.readObject();} }

User 類實現了 Externalizable 接口,并且有一個帶參數的構造方法。

public class Test{public static void main(String[] args) throws Exception {File file = new File("d:\\a.user");ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file));User user1 = new User("zhangsan", "123456");oos.writeObject(user1);System.out.println("-------序列化成功");ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));User user2 = (User) ois.readObject();System.out.println(user2);System.out.println("-------反序列化成功");} }

執行 Test.main() 方法,執行結果:

——-序列化成功
Exception in thread “main” java.io.InvalidClassException: cn.com.infcn.serial.external.User; no valid constructor

發現報錯了,序列化成功了,而沒有發序列化成功。提示沒有有效的構造方法。
這是因為使用 Externalizable 進行反序列化時,需要有默認的構造方法,通過反射先創建出該類的實例,然后再把解析后的屬性值,通過反射賦值。

結論

使用 Externalizable 進行序列化時,必須要有默認的構造方法,而Serializable可以沒有默認的構造方法。


想了解更多精彩內容請關注我的公眾號

本人簡書blog地址:http://www.jianshu.com/u/1f0067e24ff8????
點擊這里快速進入簡書
GIT地址:http://git.oschina.net/brucekankan/
點擊這里快速進入GIT

總結

以上是生活随笔為你收集整理的Java 序列化之 Externalizable的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。