美文网首页Java基础
序列化-Externalizable接口

序列化-Externalizable接口

作者: 郭寻抚 | 来源:发表于2017-01-18 16:18 被阅读115次

    1.Externalizable接口介绍

    Java序列化除了Serializable接口之外,还有一个Externalizable接口,Externalizable是Serializable的子类。如果一个类实现了Serializable接口,那么序列化的工作是java自己完成的。如果我们自定义序列化工作,那么可以实现Externalizable接口。

    Externalizable接口有两个待实现的方法writeExternal和readExternal,具体如下。

    public interface Externalizable extends Serializable {
    
        // 通过实现该方法,实现对象的自定义序列化
        void writeExternal(ObjectOutput out) throws IOException;
    
        // 通过实现该方法,实现对象的自定义反序列化
        void readExternal(ObjectInput in) throws IOException, ClassNotFoundException;
    
    }
    

    2. 举例

    实现Externalizable接口的类,必须有public的无参构造器,因为在这种序列化机制中,需要构造器参与。

    public class User implements Externalizable {
    
        private String name;
    
        private transient String password;
    
        // 必须要有无参构造器
        public User() {
            System.out.println("constructor");
        }
    
    
        // 序列化User对象
        public void writeExternal(ObjectOutput out) throws IOException {
            System.out.println("writeExternal");
            out.writeObject(name);
            out.writeObject(password);
        }
    
        // 反序列化User对象
        public void readExternal(ObjectInput in) throws IOException,
                ClassNotFoundException {
            System.out.println("readExternal");
            name = (String) in.readObject();
            password = (String) in.readObject();
        }
    
        // 不会被执行
        private void writeObject(ObjectOutputStream out) throws IOException {
            System.out.println("writeObject");
        }
    
        // 不会被执行
        private void readObject(ObjectInputStream in) throws IOException {
            System.out.println("readObject");
        }
    
        // 在writeExternal之前执行,只是为了说明执行顺序,实际不需要写。
        private Object writeReplace() throws ObjectStreamException {
            this.setName("kobe");
            System.out.println("writeReplace");
            return this;
        }
    
        // 在readExternal之后执行,只是为了说明执行顺序,实际不需要写。
        private Object readResolve() throws ObjectStreamException {
            this.setName("kobe");
            System.out.println("readresolve");
            return this;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getPassword() {
            return password;
        }
    
        public void setPassword(String password) {
            this.password = password;
        }
    
        @Override
        public String toString() {
            return "User{" +
                    ", name='" + name + '\'' +
                    ", password='" + password + '\'' +
                    '}';
        }
    }
    

    3. 和Serializable接口对比

    Serializable开发相对简单,Externalizable需要我们自行实现序列化和反序列化。

    网上有的文章说相比Serializable,Externalizable序列化的速度更快,而且数据更小。根据本人的测试,Externalizable序列化后的文件确实小,但速度却没有Serializable快。

    不管如何,Externalizable给了我们另外一种控制序列化的方式。

    测试的办法是:两个相同内容的User类,一个实现Serializable接口,一个实现Externalizable接口,然后使用ObjectOutputStream out = new ObjectOutputStream(new ByteArrayOutputStream());循环写出去n次。无论n=1000、1w、10w,都是Serializable接口更快一些。

    4. 方法在什么时候被调用

    我们在User类中实现的writeExternal和readExternal方法,是在ObjectOutputStream和ObjectInputStream中被调用的。以writeExternal为例,其调用的方法顺序如下:

    1.ObjectOutputStream.writeObject(Object obj)
    2.ObjectOutputStream.writeObject0(Object obj, boolean unshared)
    3.ObjectOutputStream.writeOrdinaryObject(Object obj,
                                     ObjectStreamClass desc,
                                     boolean unshared)
    4.ObjectOutputStream.writeExternalData(Externalizable obj)
    5.User.writeExternal(ObjectOutput out)
    

    (完)

    相关文章

      网友评论

        本文标题:序列化-Externalizable接口

        本文链接:https://www.haomeiwen.com/subject/vzcbbttx.html