JAVA SE 基础复习-IO与序列化(3)

  Java平台允许我们在内存中创建可复用的Java对象,但一般情况下,只有当JVM处于运行时,这些对象才可能存在,即,这些对象的生命周期不会比JVM的生命周期更长。但在现实应用中,就可能要求在JVM停止运行之后能够保存(持久化)指定的对象,并在将来重新读取被保存的对象。Java对象序列化就能够帮助我们实现该功能。

  使用Java对象序列化,在保存对象时,会把其状态保存为一组字节,在未来,再将这些字节组装成对象。必须注意地是,对象序列化保存的是对象的"状态",即它的成员变量。由此可知,对象序列化不会关注类中的静态变量。

  下面举一个简单的序列化的例子

import java.io.Serializable;


public class Stu implements Serializable,Cloneable{
    String name;
    int 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;
    }
    public String toString()
    {
        return "age="+age+"   name="+name;
    }
    public Object clone()
    {
        Stu stu=null;
        try{
            stu=(Stu)super.clone();
        }catch(CloneNotSupportedException ex)
        {
            ex.printStackTrace();
        }
        return stu;
    }
}
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;


public class Test {
    static class League implements Serializable,Cloneable
    {
        int level;
        Stu stu;
        public int getLevel() {
            return level;
        }
        public void setLevel(int level) {
            this.level = level;
        }
        public Stu getStu() {
            return stu;
        }
        public void setStu(Stu stu) {
            this.stu = stu;
        }
        public String toString()
        {
            return "level="+level+"    age="+stu.getAge()+"   name="+stu.getName();
        }
        
        public Object clone()
        {
            League league=null;
            try{
                league=(League)super.clone();
            }catch(CloneNotSupportedException ex)
            {
                ex.printStackTrace();
            }
            league.stu=(Stu)stu.clone();
            return league;
        }
    }
    public static void main(String[] args)
    {
        File file =new File("C:/league.txt");
        try{
            ObjectOutputStream objectOutputStream=new ObjectOutputStream(new FileOutputStream(file));
            Stu stu=new Stu();
            stu.setAge(10);
            stu.setName("ZHANG");
            League league=new League();
            league.setLevel(2);
            league.setStu(stu);
            objectOutputStream.writeObject(league);
            objectOutputStream.close();
            
            ObjectInputStream oInputStream=new ObjectInputStream(new FileInputStream(file));
            League lea=(League)oInputStream.readObject();
            oInputStream.close();
            System.out.println(lea.toString());
        }catch(IOException ex)
        {
            ex.printStackTrace();
        }catch (ClassNotFoundException ex) {
            // TODO: handle exception
            ex.printStackTrace();
        }
    }
}

输出:

level=2    age=10   name=ZHANG

我们可以看到,读取到的对象与保存的对象状态一样。这里有几点需要说明一下:

1、基本类型 的数据可以直接序列化

2、对象要被序列化,它的类必须要实现Serializable接口;如果一个类中有引用类型的实例变量,这个引用类型也要实现Serializable接口。比如上面 的例子中,League类中有一个Stu类型 的实例就是,要想让League的对象成功序列化,那么Stu也必须要实现Serializable接口。

3、我们看这个语句:

ObjectOutputStreamout  = newObjectOutputStream(new FileOutputStream(file));

我们知道 FileOutputStream类有一个带有两个参数的重载Constructor——FileOutputStream(String,boolean),其第二个参数如果为true且String代表的文件存在,那么将把新的内容写到原来文件的末尾而非重写这个文件,这里我们不能用这个版本的构造函数,也就是说我们必须重写这个文件,否则在读取这个文件反序列化的过程中就会抛出异常,导致只有我们第一次写到这个文件中的对象可以被反序列化,之后程序就会出错。

下面的问题是如果 我们上面 用到的Stu类没有实现Serializable接口,但是我们还想序列化League类的对象 ,怎么办。

Java为我们提供了transient这个关键字。如果一个变量被声明成transient,那么 在序列化的过程 中,这个变量是会被无视的,即这个变量无法被序列化。

小弟菜鸟一枚,初来乍到,有什么错误还望各位大神不吝指出,^_^。
原文地址:https://www.cnblogs.com/maydow/p/4461264.html