ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
# Java 外部化示例 – 更有效的序列化 > 原文: [https://howtodoinjava.com/java/serialization/java-externalizable-example/](https://howtodoinjava.com/java/serialization/java-externalizable-example/) 默认的 Java 序列化效率不高。 如果您序列化了一个具有许多属性和属性的胖对象,则您不希望出于任何原因进行序列化(例如,它们始终被分配默认值),您将需要处理繁重的对象并通过网络发送更多字节,这在某些情况下可能会非常昂贵。 要解决此问题,您可以通过实现[`Externalizable`](https://docs.oracle.com/javase/7/docs/api/java/io/Externalizable.html)接口并覆盖其方法`writeExternal()`和`readExternal()`来编写自己的序列化逻辑。 通过实现这些方法,您将告诉 JVM 如何编码/解码对象。 出于示例目的,我创建了这个简单的类,我们将使用`writeExternal()`和`readExternal()`方法进行序列化和反序列化。 ```java class UserSettings implements Externalizable { //This is required public UserSettings(){ } private String doNotStoreMe; private Integer fieldOne; private String fieldTwo; private boolean fieldThree; public String getDoNotStoreMe() { return doNotStoreMe; } public void setDoNotStoreMe(String doNotStoreMe) { this.doNotStoreMe = doNotStoreMe; } public Integer getFieldOne() { return fieldOne; } public void setFieldOne(Integer fieldOne) { this.fieldOne = fieldOne; } public String getFieldTwo() { return fieldTwo; } public void setFieldTwo(String fieldTwo) { this.fieldTwo = fieldTwo; } public boolean isFieldThree() { return fieldThree; } public void setFieldThree(boolean fieldThree) { this.fieldThree = fieldThree; } public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { fieldOne = in.readInt(); fieldTwo = in.readUTF(); fieldThree = in.readBoolean(); } public void writeExternal(ObjectOutput out) throws IOException { out.writeInt(fieldOne); out.writeUTF(fieldTwo); out.writeBoolean(fieldThree); } @Override public String toString() { return "UserSettings [doNotStoreMe=" + doNotStoreMe + ", fieldOne=" + fieldOne + ", fieldTwo=" + fieldTwo + ", fieldThree=" + fieldThree + "]"; } } ``` ## `Externalizable`的`writeExternal()`示例 [`writeExternal()`](https://docs.oracle.com/javase/7/docs/api/java/io/Externalizable.html#writeExternal%28java.io.ObjectOutput%29)方法用于提供序列化逻辑,即将类的字段写入字节。 在读回序列化的对象之后,您可以自由地仅存储要返回的那些字段,忽略其余字段。 ```java public void writeExternal(ObjectOutput out) throws IOException { //We are not storing the field 'doNotStoreMe' out.writeInt(fieldOne); out.writeUTF(fieldTwo); out.writeBoolean(fieldThree); } ``` ## `Externalizable`的`readExternal()`示例 唯一需要记住的是 – [`readExternal()`](https://docs.oracle.com/javase/7/docs/api/java/io/Externalizable.html#readExternal%28java.io.ObjectInput%29)方法必须读取与`writeExternal()`写入的序列相同且类型相同的值。 ```java public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { fieldOne = in.readInt(); fieldTwo = in.readUTF(); fieldThree = in.readBoolean(); } ``` ## 完整的例子 现在,让我们编写代码进行序列化并读回字节,以验证 JVM 是否遵守契约。 ```java public class ExternalizableExample { public static void main(String[] args) { UserSettings settings = new UserSettings(); settings.setDoNotStoreMe("Sensitive info"); settings.setFieldOne(10000); settings.setFieldTwo("HowToDoInJava.com"); settings.setFieldThree(false); //Before System.out.println(settings); storeUserSettings(settings); UserSettings loadedSettings = loadSettings(); System.out.println(loadedSettings); } private static UserSettings loadSettings() { try { FileInputStream fis = new FileInputStream("object.ser"); ObjectInputStream ois = new ObjectInputStream(fis); UserSettings settings = (UserSettings) ois.readObject(); ois.close(); return settings; } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } return null; } private static void storeUserSettings(UserSettings settings) { try { FileOutputStream fos = new FileOutputStream("object.ser"); ObjectOutputStream oos = new ObjectOutputStream(fos); oos.writeObject(settings); oos.close(); } catch (IOException e) { e.printStackTrace(); } } } ``` ```java Output: UserSettings [doNotStoreMe=Sensitive info, fieldOne=10000, fieldTwo=HowToDoInJava.com, fieldThree=false] UserSettings [doNotStoreMe=null, fieldOne=10000, fieldTwo=HowToDoInJava.com, fieldThree=false] ``` 显然,我们可以取回所需的字段,而忽略不需要的字段,这就是`Externalizable`接口的全部目的。 学习愉快!