美文网首页
Externalizable的用法及与Serializable的

Externalizable的用法及与Serializable的

作者: 咖A喱 | 来源:发表于2019-03-03 13:22 被阅读0次

用法

  • Externalizalbe拓展了Serializable接口,Serializable接口更类似一个标记,没有方法,而Externalizable需要重写writeExternal 和 readExternal方法
  • 可以序列化的对象包括:基本数据类型、所有的集合类以及其他class对象
  • 对象序列化不仅是该对象,还包括内含的所有对象

序列化的步骤

  1. 创建OutputStream对象: OutputStream outputStream = new FileOutputStream("output.txt")
  2. 封装到ObjectOutputStream对象中:ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream)
  3. 调用writeObject 方法实现序列化:objectOutputStream.writeObject(Object)
  4. 最后记得关闭资源:
    objectOutputStream.close(), outputStream .close()

反序列化的步骤

  1. 首先要创建OutputStream对象:InputStream inputStream= new FileInputStream("output.txt")
  2. 将其封装到ObjectInputStream对象内:ObjectInputStream objectInputStream= new ObjectInputStream(inputStream);
  3. 调用readObject()即可完成对象的反序列化:objectInputStream.readObject();
  4. 最后关闭资源:objectInputStream.close()inputStream.close();

用法实例

讲解

  1. 创建了一个User类,有usernamepassword的属性,实现了Serializable的接口
package main.java.dai.model;

import java.io.Serializable;

public class User implements Serializable {
    private static final long serialVersionUID = 1L;
    private String username;
    private String password;

    public User(String username, String password) {
        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;
    }
}
  1. 创建了一个Gamer类,有User、name、age的属性,实现了Serializable的接口
package main.java.dai.model;

import java.io.Serializable;

public class Gamer implements Serializable {
    private static final long serialVersionUID = 1L;
    private User user;
    private String name;
    private transient int age;

    public Gamer(User user, String name, int age) {
        this.user = user;
        this.name = name;
        this.age = age;
    }

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}
  1. 创建了一个Man类,有name、age的属性,实现了Externalizable的接口,重写了writeExternalreadExternal的方法
package main.java.dai;

import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;

public class Man implements Externalizable {
    private String name;
    private int age;

    public Man() {
        System.out.println("man constructor");
    }

    public Man(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public void writeExternal(ObjectOutput out) throws IOException {
        System.out.println("write external");
        out.writeObject(name);
        out.writeObject(age);
    }

    @Override
    public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
        System.out.println("read external");
        name = (String) in.readObject();
        age = in.readInt();
    }

}
  1. 创建了主函数,用作测试,分别有writeSerivalizableObjectreadSerializableObjectwriteExternalizableObjectreadExternalizableObject的方法
package main.java.dai;

import main.java.dai.model.Gamer;
import main.java.dai.model.User;

import java.io.*;

public class Main {
    public static void main(String[] args) {
        System.out.println("Serivalizable demo:");
        writeSerivalizableObject();
        readSerializableObject();
        System.out.println("Externalizable demo:");
        writeExternalizableObject();
        readExternalizableObject();
    }

    public static void writeSerivalizableObject() {
        try {
            User user = new User("daiyuanli", "123456");
            Gamer gamer = new Gamer(user, "代元丽", 20);
            ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("output.txt"));//使用匿名函数之后不必close
            objectOutputStream.writeObject("string");//试试序列化String类型
            objectOutputStream.writeObject(gamer);//序列化gamer的同时也会序列化user
            objectOutputStream.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void readSerializableObject(){
        try{
            ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("output.txt"));
            String string =(String) objectInputStream.readObject();
            Gamer gamer = (Gamer) objectInputStream.readObject();
            objectInputStream.close();
            System.out.println("String"+string+",name:"+gamer.getName()+",age:"+gamer.getAge()+",User = [ usernam:"+gamer.getUser().getUsername()+",password:"+gamer.getUser().getPassword()+"]");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
    public static void writeExternalizableObject(){
        Man man = new Man("张山",22);
        try{
            ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("externalizable.txt"));
            objectOutputStream.writeObject(man);
            objectOutputStream.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    public static void readExternalizableObject(){
        try{
            ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("externalizable.txt"));
            Man man = (Man) objectInputStream.readObject();
            objectInputStream.close();
            System.out.println("name:"+man.getName()+",age:"+man.getAge());
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

输出结果

Stringstring,name:代元丽,age:0,User = [ usernam:daiyuanli,password:123456]
Externalizable demo:
write external
man constructor
name:张山,age:22

异同

  1. 序列化责任

    当类实现Serializable的接口时,Jvm完全负责序列化,而使用Externalizable的情况下,程序员负责整个序列化和反序列化过程

  2. 用法

    序列化一整个对象时,例如上例中的gamer,使用Serialzable接口更适合,而自定义序列化,使用Externalizable可以控制流程

  3. 性能:

Serializable接口使用反射和元数据,相对较慢的性能

  1. 自定义序列化

    实现Serializable接口的类使用transient关键字可以保证在序列化对象的过程中,该属性不被序列化,但JVM仍会将该字段的默认值加载进文件中

相关文章

网友评论

      本文标题:Externalizable的用法及与Serializable的

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