java对象序列化

定义:

  对象序列化目标是将对象保存在磁盘中,允许在网络中直接传输对象。序列化机制把内存中的java对象转化成与平台无关的二进制流,从而可以把这种二进制

流永久的保存在磁盘上,通过网络把二进制流传送到另一个网络节点,其他程序一旦获得了二进制流,不管是从磁盘还是网络获取的,都可以将此转换成java对象。

 

如果要把某个对象序列化,这个对象必须要实现Serializable接口,实现此接口无需实现任何方法,此接口只是告诉java此对象是可以被序列化的。

此接口是一个标记接口。  

被序列化的User对象,

 

import java.io.Serializable;

public class User implements Serializable{
    private String name;
    private 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;
    }
}

 

将User对象序列化,创建一个输出流输出到磁盘

public static void main(String[] args) throws Exception{
        FileOutputStream fos = new FileOutputStream("d:/object.txt");
        ObjectOutputStream oos =new ObjectOutputStream(fos);
        
        User u =new User();
        u.setName("jack");
        u.setAge(43);
        
        oos.writeObject(u);
    }

反序列化,创建一个输入流,从磁盘读取

public static void main(String[] args) throws Exception{
        FileInputStream fis = new FileInputStream("d:/object.txt");
        ObjectInputStream ois =new ObjectInputStream(fis);
        
        User u =(User)ois.readObject();
        //输出 jack    43
        System.out.println(u.getName() +"\t"+u.getAge());
    }

由此,序列化还是很容易理解的

还有几点说明:

  1.反序列化不是通过构造器来初始化java对象的,可以用构造方法来验证。

  2.如果序列化向文件中写入了多个对象,反序列化必须按照实际写入的顺序读取。

  3.如果被序列化对象的直接或间接父类是不可序列化的,只带有无参数构造器,改父类定义的成员不会被序列化。

    4.被序列化的引用类也必须实现Serializable接口; 

对象引用序列化:

  序列化对象Person 有一个User对象的引用:

import java.io.Serializable;

public class Person implements Serializable{
    private String id ;
    private User u;
    
    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    public User getU() {
        return u;
    }
    public void setU(User u) {
        this.u = u;
    }
}

 

  如果某对象被其他多个不同对象引用,需要序列化,java不会对同意对象做多次序列化,因此java序列有特殊算法(序列化底层机制):

  *所有保存到磁盘的序列化对象都有一个编号。

  *当程序试图序列化对象时,java会先检查此对象在本次虚拟机中是否被序列化过。

  *如果被序列化过,则输出上次序列化的编号,而不是重新序列化改对象。

那么,做个重复序列化测试

    public static void main(String[] args)  {
        try{
            FileOutputStream fos = new FileOutputStream("d:/object.txt");
            ObjectOutputStream oos =new ObjectOutputStream(fos);
            
            FileInputStream fis = new FileInputStream("d:/object.txt");
            ObjectInputStream ois =new ObjectInputStream(fis);
            
            User u =new User();
            u.setName("第一次序列化");
            oos.writeObject(u);
            u.setName("第二次序列化");
            oos.writeObject(u);
            //读取流
            ois.readObject();
            User ui =(User)ois.readObject();
            //发现输出 : 第一次序列化
            System.out.println(ui.getName() );
        }catch(Exception e){
            e.printStackTrace();
        }
    }

发现结果符合它的机制的确没有做二次序列化,即使对象的属性被修改

 

posted on 2014-10-30 20:52  __精彩  阅读(226)  评论(0编辑  收藏  举报

导航