理解java序列化

一、序列化是什么

      在jvm中引用数据类型存在于栈中,而new创建出的对象存在于堆中。如果电脑断电那么存在于内存中的对象就会丢失。那么有没有方法将对象保存到磁盘(对象持久化存储)或通过网络传输到远处的其他地方呢?
答案是可以,但是我们必须要求所有支持持久化存储的类实现Serializable接口。原因是,jvm不仅需要考虑将对象存储到硬盘等其他介质,还需要考虑将其读取(反序列化)出来。

如果读取在硬盘中的对象不能被创建它的类识别,岂不会产生问题?序列化就是起到告诉JVM,这个对象是由哪个类创建的。

   对于jvm来说,要进行持久化的类必须要有个标记,相当于一个通行证,只有持有这个通行证,jvm才让类创建的对象进行持久化。这个通行证就是Serializable接口,这个接口将类与一个称为serialVersionUID的变量关联起来,这个serialVersionUID就是在反序列化中用来确定由哪个类来加载这个对象。

说明白点序列化是将对象状态转换为可保持或传输的格式的过程,就是你可以用对象输出流输出到文件.

二、实现Serializable接口的例子

  这个例子的作用是将一个学生信息存储到磁盘中,然后再将其读取出来:

public class student implements Serializable {  
  
    public static  String countryName="china";  
    private int id;  
    private String name;  
    private String sex;  
  
    public String getSex() {  
  
        return sex;  
    }  
  
    public void setSex(String sex) {  
        this.sex = sex;  
    }  
  
    public int getId() {  
        return id;  
    }  
  
    public void setId(int id) {  
        this.id = id;  
    }  
public String getName() { String s="adaf"; return name; } public void setName(String name) { this.name = name; } }

  

public class ObjectStreamDemo {  
    public static void main(String[] args) {  
        //writeObj();  
        readObj();  
    }  
    public static  void writeObj()  
    {  
        student s=new student();  
        s.setId(8);  
        s.setName("张三");  
        s.countryName="USA";  
        try {  
            ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("c:\\obj.txt"));  
            oos.writeObject(s);  
            oos.close();  
        } catch (IOException e) {  
            e.printStackTrace();  
        }  
    }  
    public  static  void  readObj()  
    {  
        try {  
            ObjectInputStream ooi=new ObjectInputStream(new FileInputStream("c:\\obj.txt"));  
            try {  
                Object obj=ooi.readObject();  
                student s=(student)obj;  
                //person s=(person)obj;  
                System.out.println("id:"+s.getId()+",name:"+s.getName()+s.countryName);  
            } catch (ClassNotFoundException e) {  
                e.printStackTrace();  
            }  
            ooi.close();  
        } catch (IOException e) {  
            e.printStackTrace();  
        }  
    }  
}  

  

可以看到程序正常运行,但是我们给student类添加一个成员变量private string school,那么则在读取时候抛出异常:

java.io.InvalidClassException:com.lei.lock.student; local class incompatible: stream classdescserialVersionUID = 5039200702392716702, local class serialVersionUID =-858199357477413536

大意为:本地类不匹配:保存在本地的文件描述类序列号为5039200702392716702 ,而当前类的序列号为-858199357477413536。因此我们可以得出结论,如果不指定serialVersionUID,那么其值是和类中的成员变量相关联的。

同时需要注意,持久化的数据均为存在于堆中的数据,static类型的数据存在于方法区中,不能被持久化。如果想不持久化某个成员变量,则需要在成员变量加上关键字transient

三、自定义serialVersionUID

 既然是由serialVersionUID来决定由哪个类来加载存在于文件中的对象,那么我们能不能指定serialVersionUID的数值,使得其不再与类的成员变量相关联呢?答案是肯定的。

例如:

需要注意的地方是,serialVersionUID不是决定由哪个类加载硬盘文件中的唯一因素,类的包名、类的名称都有关联。如果不一致,也会出现类型转化错误。原因是类的包名,类名已经被写入了文件当中。

public class student implements Serializable {  
  
    public static  String countryName="china";  
    private int id;  
    private String name;  
    private String sex;  
  
    private String school;  
    private static final long serialVersionUID = -5182532647273106745L;  
    //如果想对非静态的数据也不想序列化,则需要加入关键字  
    transient int height;//身高不存储到文件系统或者数据库中  
    public static String getCountryName() {  
        return countryName;  
    }  
  
    public static void setCountryName(String countryName) {  
        student.countryName = countryName;  
    }  
  
    public int getHeight() {  
        return height;  
    }  
  
    public void setHeight(int height) {  
        this.height = height;  
    }  
  
    public String getSex() {  
  
        return sex;  
    }  
  
    public void setSex(String sex) {  
        this.sex = sex;  
    }  
  
    public int getId() {  
        return id;  
    }  
  
    public void setId(int id) {  
        this.id = id;  
    }  
public String getName() { String s="adaf"; return name; } public void setName(String name) { this.name = name; } }

  

 

posted @ 2017-11-23 12:09  wangchuan886  阅读(234)  评论(0编辑  收藏  举报