java 序列化

  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,那么 在序列化的过程 中,这个变量是会被无视的,即这个变量无法被序列化。

你可能感兴趣的:(java)