• [转]Serializable接口与Externalizable接口区别


    被Serializable接口声明的类的对象的内容都将被序列化,如果现在用户希望自己指定序列化的内容,则可以让一个类实现Externalizable接口,此接口定义如下:

    1 public interface Externalizable extends Serializable { 
    2     public void writeExternal(ObjectOutput out) throws IOException;
    3     public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException; 
    4 }

    Externalizable接口是Serializable接口的子接口,在此接口中定义了两个方法,这两个方法的作用如下。

    writeExternal(ObjectOutputout):在此方法中指定要保存的属性信息,对象序列化时调用。

    readExternal(ObjectInputin):在此方法中读取被保存的信息,对象反序列化时调用。

    这两个方法的参数类型是ObjectOutput和ObjectInput,两个接口的定义如下。

    ObjectOutput接口定义:

    1. public interface ObjectOutput extends DataOutput 

    ObjectInput接口定义:

    1. public interface ObjectInput extends DataInput 

    可以发现以上两个接口分别继承DataOutput和DataInput,这样在这两个方法中就可以像DataOutputStream和DataInputStream那样直接输出和读取各种类型的数据。

    如果一个类要使用Externalizable实现序列化时,在此类中必须存在一个无参构造方法,因为在反序列化时会默认调用无参构造实例化对象,如果没有此无参构造,则运行时将会出现异常,这一点的实现机制与Serializable接口是不同的。

    范例:修改Person类并实现Externalizable接口

    
    
     1 package org.lxh.demo12.serdemo; 
     2 import java.io.Externalizable; 
     3 import java.io.IOException; 
     4 import java.io.ObjectInput; 
     5 import java.io.ObjectOutput;
     6 
     7 // 此类的对象可以被序列化
     8 public class Person implements Externalizable {
     9 
    10     private String name;                      // 声明name属性 
    11 
    12     private int age;                          // 声明age属性 
    13 
    14     public Person(){}                        // 必须定义无参构造 
    15 
    16     public Person(String name, int age) {    // 通过构造方法设置属性内容 
    17         this.name = name; 
    18         this.age = age; 
    19     } 
    20 
    21     public String toString() {                 // 覆写toString()方法 
    22         return "姓名:" + this.name + ";年龄:" + this.age; 
    23     } 
    24 
    25     // 覆写此方法,根据需要读取内容,反序列化时使用 
    26     public void readExternal(ObjectInput in) throws IOException, 
    27             ClassNotFoundException { 
    28         this.name = (String)in.readObject() ;  // 读取姓名属性 
    29         this.age = in.readInt() ;             // 读取年龄 
    30     } 
    31     // 覆写此方法,根据需要可以保存属性或具体内容,序列化时使用  
    32     public void writeExternal(ObjectOutput out) throws IOException { 
    33         out.writeObject(this.name) ;         // 保存姓名属性 
    34         out.writeInt(this.age) ;            // 保存年龄属性 
    35     } 
    36 } 

    以上程序中的Person类实现了Externalizable接口,这样用户就可以在类中有选择地保存需要的属性或者其他的具体数据。在本程序中,为了与之前的程序统一,将全部属性保存下来。

    范例:序列化和反序列化Person对象

     1 package org.lxh.demo12.serdemo; 
     2 import java.io.File; 
     3 import java.io.FileInputStream; 
     4 import java.io.FileOutputStream; 
     5 import java.io.InputStream; 
     6 import java.io.ObjectInputStream; 
     7 import java.io.ObjectOutputStream; 
     8 import java.io.OutputStream; 
     9 public class SerDemo03 { 
    10     public static void main(String[] args) throws Exception { 
    11         ser();                              // 序列化 
    12         dser();                               // 反序列化 
    13     } 
    14     public static void ser() throws Exception {     // 序列化操作 
    15         File f = new File("D:" + File.separator + "test.txt"); 
    16         ObjectOutputStream oos = null; 
    17         OutputStream out = new FileOutputStream(f); // 文件输出流 
    18         oos = new ObjectOutputStream(out);       // 为对象输出流实例化 
    19         oos.writeObject(new Person("张三", 30));  // 保存对象到文件 
    20         oos.close();                            // 关闭输出 
    21     } 
    22     public static void dser() throws Exception {        // 反序列化操作 
    23         File f = new File("D:" + File.separator + "test.txt"); 
    24         ObjectInputStream ois = null; 
    25         InputStream input = new FileInputStream(f); // 文件输出流 
    26         ois = new ObjectInputStream(input);         // 为对象输出流实例化 
    27         Object obj = ois.readObject();          // 读取对象 
    28         ois.close();                           // 关闭输出 
    29         System.out.println(obj); 
    30     } 
    31 } 

    从以上代码中可以发现,使用Externalizable接口实现序列化明显要比使用Serializable接口实现序列化麻烦得多,除此之外,两者的实现还有不同,如表12-27所示。

    表12-27 Externalizable接口与Serializable接口实现序列化的区别

       号

       别

    Serializable

    Externalizable

    1

    实现复杂度

    实现简单,Java对其

    有内建支持

    实现复杂,

    由开发人员自己完成

    2

    执行效率

    所有对象由Java统一保存,

    性能较低

    开发人员决定哪个对象保存,

    可能造成速度提升

    3

    保存信息

    保存时占用空间大

    部分存储,

    可能造成空间减少

    在一般的开发中,因为Serializable接口的使用较为方便,所以出现较多

  • 相关阅读:
    仿联想商城laravel实战---6、自建配置文件和缓存(如何读取自己创建的配置文件的信息)
    php中相对路径和绝对路径如何使用(详解)
    英语影视台词---绿皮书(2)(利普 我以为你要把那家伙打死了)
    仿联想商城laravel实战---5、无刷新的增删改查(动态页面更新的三种方式(html))
    英语发音规则---ea字母组合发音规律
    英语发音规则---ir字母组合发音规律
    仿联想商城laravel实战---4、验证(lavarel的表单验证如何使用)
    android adb 不同的方式使用特定的解释
    Spring aop 小例子demo
    SPOJ 15. The Shortest Path 堆优化Dijsktra
  • 原文地址:https://www.cnblogs.com/atai/p/9485548.html
Copyright © 2020-2023  润新知