一:对象的序列化是指把对象写入到各种介质中的过程。这样可以不用拷贝整个类文件回家,只需要拷贝这个序列化之后的文件就可以。可以序列化的实体类必须实现implements Serializable接口,这样才不会抛出java.io.NotSerializableException不可序列化异常。特别注意的几点:

◆transient修饰的属性,在文件中没写进去,控制台输出类型的默认值

◆static修饰的属性,在文件中没写进去,控制台仍可以输出

◆和实体类相关联的类也必须implements Serializable接口

 二:ObjectOutputStream/ObjectInputStream对象输入输出流

他和前面一节我们介绍的包装流的用法一致,他可以用来读操作对象至文件中。

三:具体实现

   实体Address类:此类为和Person类相关联的类,因此必须实现序列化接口

public class Address implements Serializable{
    private String city;
    private String street;
    //其他方法省略,请自行添加
}

   实体Person类:要实现对象序列化,所以也应该实现序列化接口

public class Person implements Serializable{
    /*static*/ private String name;//static修饰的文件中没写进去,控制台可以输出
    /*transient*/ private int age;//transient修饰的文件中没写进去,控制台输出类型的默认值
    private Address address;
        //其他方法省略,请自行添加
}

1 单个对象的可序列化的测试类:

public class TestOOSOIS {
    public static void main(String[] args) throws Exception {
        //单个对象的可序列化
        File file = new File("d:\\a.txt");//创建文件
        FileOutputStream os = new FileOutputStream(file);//创建基础输出流
        ObjectOutputStream oos = new ObjectOutputStream(os);//创建包装基础输出流的流
        Person obj = new Person("张三",22);//定义单个对象
        Address address = new Address("哈尔滨","和兴路");
        obj.setAddress(address);
        oos.writeObject(obj);//把单个对象写进文件里
                                                                                                                                                                                                                                                                                                                                                                                                                                                                              
        FileInputStream fis = new FileInputStream(file);//创建基础输入流
        ObjectInputStream ois = new ObjectInputStream(fis);//创建包装基础输入流的流
        Person p = (Person) ois.readObject();//读出一个Person对象
        System.out.println("姓名:"+p.getName());
        System.out.println("年龄:"+p.getAge());
    }
}

结果:

姓名:张三
年龄:22

2 用异常实现多个对象的序列化。多个对象的序列化会抛出“EOFException”这种异常, 那么在catch中可以给出提示信息,以便处理掉,但是有点影响代码的阅读。

测试类如下:

//用异常实现多个对象的序列化
public class TestSer {
    public static void main(String[] args) throws Exception  {
        Person p1 = new Person("张三",22);//定义多个对象
        Person p2 = new Person("李四",32);
        File file = new File("d:\\a.txt");
        FileOutputStream os = new FileOutputStream(file);
        ObjectOutputStream oos = new ObjectOutputStream(os);
                                                                                                                                                                                                                                                                                                                                                                                                                    
        oos.writeObject(p1);//写入多个对象
        oos.writeObject(p2);
                                                                                                                                                                                                                                                                                                                                                                                                                    
        FileInputStream fis = new FileInputStream(file);
        ObjectInputStream ois = new ObjectInputStream(fis);
                                                                                                                                                                                                                                                                                                                                                                                                                    
        while(true){//死循环
            Person p;
            try {
                p = (Person) ois.readObject();
                System.out.println(p);
            } catch (IOException e) {         
                System.out.println("读到了文件的末尾。。。");
                break;//用异常作为循环判定条件
            }
        }
                                                                                                                                                                                                                                                                                                                                                                                                                    
        oos.close();
        ois.close();
    }
}

   结果2:

Person [name=张三, age=22, addressnull]
Person [name=李四, age=32, addressnull]
读到了文件的末尾。。。

3运用集合实现多个对象的序列化。他所采用的方法是:把多个对象存入一个ArrayList中,让后把这个集合写入到文件里的过程,然后读取是以集合的形式去读。

具体的测试类:

//运用集合实现多个对象的序列化,推荐使用
public class TestSerCol {
    public static void main(String[] args) throws Exception {
        Person p1 = new Person("张三",22);//定义多个对象
        Person p2 = new Person("李四",32);
        File file = new File("d:\\a.txt");
        FileOutputStream os = new FileOutputStream(file);
        ObjectOutputStream oos = new ObjectOutputStream(os);
        ArrayList<Person> list = new ArrayList<Person>();//定义集合存放Person类
        list.add(p1);
        list.add(p2);
        oos.writeObject(list);//写list到文件中 
        FileInputStream fis = new FileInputStream(file);
        ObjectInputStream ois = new ObjectInputStream(fis);
        ArrayList<Person> perlist = (ArrayList<Person>) ois.readObject();
        for(Person p:perlist){//根据list输出
            System.out.println(p);
        }
    }
}

   结果:

Person [name=张三, age=22, addressnull]
Person [name=李四, age=32, addressnull]

4:一个对象的多次序列化

同一个流对同一个对象的多次序列化,不关心属性的变化,存入的仍是这个对象的引用。比如有一个对象姓名张三,年龄23,当把张三变为李四时,读出的仍然是“张三23”,所以说两者的地址相同。

public class TestManyOBJ {
    public static void main(String[] args) throws Exception  {
        Person p1 = new Person("张三",22);//定义一个对象
        Address add = new Address();
        add.setCity("哈尔滨");
        add.setStreet("和兴路");
        p1.setAddress(add);
        File file = new File("d:\\a.txt");
        FileOutputStream os = new FileOutputStream(file);//基本输入流
        ObjectOutputStream oos = new ObjectOutputStream(os);//包装输入流
                                                                                                                                                        
        oos.writeObject(p1);//写入一个对象
        p1.setName("李四");
        oos.writeObject(p1);//再次写入这个对象
                                                                                                                                                        
        FileInputStream fis = new FileInputStream(file);//基本输出流
        ObjectInputStream ois = new ObjectInputStream(fis);//基本包装流   
                                                                                                                                                        
        Person p = (Person) ois.readObject();//读第一个
        System.out.println(p);
        Person p2 = (Person) ois.readObject();//读第二个
        System.out.println(p2);
                                                                                                                                                        
        System.out.println(p2==p);//由于再次写入的是p1对象的引用,所以二者地址相同     
        oos.close();
        ois.close();
    }
}

   结果:

Person [name=张三, age=22]
Person [name=张三, age=22]
true

如何解决上述的问题呢?有两种办法

(1)重新定义一个流:这样的话,在另一个新流中相当于全新的,当然可以写的进去。

public class TestManyOBJ {
    public static void main(String[] args) throws Exception  {
        Person p1 = new Person("张三",22);//定义一个对象
        Address add = new Address();
        add.setCity("哈尔滨");
        add.setStreet("和兴路");
        p1.setAddress(add);
                                                                                                                                           
        File file = new File("d:\\a.txt");//基本文件
        FileOutputStream os = new FileOutputStream(file);//基本输入流
        ObjectOutputStream oos = new ObjectOutputStream(os);//包装输入流
                                                                                                                                           
        oos.writeObject(p1);//写入一个对象
        p1.setName("李四");
        //重新定义一个流,实现对一个对象的多次序列化
        FileOutputStream os1 = new FileOutputStream(file);//新的基本输入流
        ObjectOutputStream oos1 = new ObjectOutputStream(os1);//新的包装输入流
        oos1.writeObject(p1);//再次写入这个对象
                                                                                                                                           
        FileInputStream fis = new FileInputStream(file);//基本输出流
        ObjectInputStream ois = new ObjectInputStream(fis);//基本包装流   
                                                                                                                                           
        Person p = (Person) ois.readObject();//读的是新写进去的这个
        System.out.println(p);
        oos.close();
        ois.close();
    }
}

   结果:

Person [name=李四, age=22]

(2)对象的Clone化:克隆出的对象和源对象不是同一个,所以也仍然可以写的进去。这时应该注意:实体类应该实现Cloneable接口,并且重写clone()方法。

具体的测试如下:

public class TestManyOBJ {
    public static void main(String[] args) throws Exception  {
        Person p1 = new Person("张三",22);//定义一个对象
        Address add = new Address();
        add.setCity("哈尔滨");
        add.setStreet("和兴路");
        p1.setAddress(add);
                                                                                                                        
        File file = new File("d:\\a.txt");//基本文件
        FileOutputStream os = new FileOutputStream(file);//基本输入流
        ObjectOutputStream oos = new ObjectOutputStream(os);//包装输入流
                                                                                                                        
        oos.writeObject(p1);//写入一个对象
        p1.setName("李四");
        //运用克隆,实现对一个对象的多次序列化     
        oos.writeObject(p1.clone());//运用再次写入这个对象
                                                                                                                        
        FileInputStream fis = new FileInputStream(file);//基本输出流
        ObjectInputStream ois = new ObjectInputStream(fis);//基本包装流   
                                                                                                                        
        Person p = (Person) ois.readObject();//读的是原来进去的这个
        System.out.println(p);
        Person p2 = (Person) ois.readObject();//读的是新写进去的这个
        System.out.println(p2);
                                                                                                                        
        oos.close();
        ois.close();
    }
}

   结果:

Person [name=张三, age=22]
Person [name=李四, age=22]


    5:细心的你可能会发现,在实体类中会出现一个×××三角的小图标,点进去会让你添加一个序列号,这个可以作为版本信息号,方便于以后的交流。(了解一下就可以)


对象序列化的简析先到这里咯。。。来个美容觉吧。。。简析对象序列化_java对象序列化