Java教程—IO流之对象的序列化和反序列化

什么是序列化和反序列化


• 序列化是把对象转换为字节序列的过程
• 反序列化是把字节序列恢复为对象的过程


序列化能做什么


序列化能将一个任意复杂的Java对象保存到磁盘文件中,或在网络中进行传输。


序列化的实现


java.io中的对象流提供了序列化和反序列化对象的方法
• 对象输出流 ObjectOutputStream
构造方法:
ObjectOutputStream(OutputStream out)
保存对象的方法:
void writeObject(Object obj)

• 对象输入流ObjectInputStream
构造方法:
ObjectInputStream(InputStream out)
读取对象方法:
Object readObject()


序列化要注意的地方


1.    只有实现了Serializable或Externalizable接口的对象,才能序列化,否则会抛出java.io.NotSerializableException
2.    如果父类实现了Serializable接口,子类可以不实现该接口
3.    类要序列化,类所有的属性也要序列化
4.    声明为static和transient类型的成员数据不能被序列化。


序列化案例代码

/**
 * 大象
 *
 */
public class Elephant implements Serializable{
    
    /**
     * 
     */
    private static final long serialVersionUID = 2483988729860853698L;
    private String name;
    private Integer age;
    private Double weight;
    
    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;
    }
    public double getWeight() {
        return weight;
    }
    public void setWeight(double weight) {
        this.weight = weight;
    }
    public Elephant(String name, int age, double weight) {
        super();
        this.name = name;
        this.age = age;
        this.weight = weight;
    }
    public Elephant() {
        super();
    }
    
    @Override
    public String toString() {
        return "Elephont [name=" + name + ", age=" + age + ", weight=" + weight + "]";
    }
    
    public void run(){
        System.out.println(name+"在跑!!!!");
    }
    
}

@Test
    public void testObjectOutput(){
        //创建对象输出流
        try(ObjectOutputStream out = new ObjectOutputStream(
                new FileOutputStream("C:/xpp/object"))){
            //存入Java对象
            out.writeObject(new Elephant("非洲大象",20,5000));
            //存入对象集合
            List list = Arrays.asList(
                    new Elephant("非洲大黑象",10,10000),
                    new Elephant("非洲小黑象",10,10000),
                    new Elephant("亚洲小黑象",10,10000),
                    new Elephant("亚洲大黑象",10,10000),
                    new Elephant("亚洲小白象",10,10000));
            out.writeObject(list);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    @Test
    public void testObjectInput(){
        //创建对象输入流
        try(ObjectInputStream in = new ObjectInputStream(
                new FileInputStream("C:/xpp/object"))){
            //读取Java对象
            Elephant elephont = (Elephant) in.readObject();
            elephont.run();
            //读取对象集合
            List list = (List) in.readObject();
            for(Elephant ele : list){
                ele.run();
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

我们看到无论是一个Java对象,或是一个Java集合都可以序列化到文件中,因为Java所有的集合也都实现了Serializable接口。
serialVersionUID的作用
当一个类实现序列化接口后,IDE会出现编译警告,并提示生成一个serialVersionUID。 也就是类中的常量:
private static final long serialVersionUID = 2483988729860853698L;
那么这个常量的作用是什么呢?
serialVersionUID是序列化类的版本号, 如果不手动添加,系统会自动添加版本号,序列化对象后,如果类的代码进行任意的修改,类版本号会改变,进行反序列化时,对象出现类型不兼容的问题InvalidClassException。
如果手动添加该常量,类修改后版本号不变,反序列化是就不会出现类型不兼容问题。


总结


•    序列化是Java的常用技术,用于将对象转换为字节序列保存到文件或网络中。
•    Java中的对象流ObjectOutputStream和ObjectInputStream提供了序列化和反序列化的方法。
•    进行序列化的对象需要实现Serializable接口
 

你可能感兴趣的:(java教程,Java小白课堂)