java中对象、基本数据的读写(serializable序列化)

java中的读写实际很多都可以算作二进制的读写,但由于对对象和基本数据的读写较为特殊,因此单独拿出来讲。

对象的读写:ObjectInputStream ObjectOutputStream
基本数据的读写:DataInputStream DataOutputStream

把对象或基本数据写到文件里的过程叫序列化(serialize),从文件中读取一个对象或基本数据叫反序列化(deserialize)
大部分类都实现了Serializable接口,自己写的类也可以实现这个接口:

import java.io.*;
class Person implements Serializable
{
    String name;
    int age;
    Person(String name, int age) {
        this.name=name;
        this.age=age;
    }
    public String toString() {
        return name + "(" + age + ")";
    }
}
public class SerializeDemo {
    public static void main (String[] args)
    throws IOException
    {
        Person [] ps = {
            new Person("Li",18),
            new Person("Wang",19)
        };
        String fileName = "s.temp";
        //Serialize
        ObjectOutputStream output = new ObjectOutputStream(
            new FileOutputStream(fileName) );
        for(Person p : ps) output.writeObject(p);
        output.close();
        //deserialize
        ObjectInputStream input = new ObjectInputStream(
            new FileInputStream(fileName) );
        Person p = null;
        try {
            while( (p=(Person)input.readObject()) != null ) {
                System.out.println(p);
            }
        } catch(ClassNotFoundException ex) {}
        catch(EOFException eofex) {}
        input.close();
    }
}

implements Serializable后eclipse会提醒:The serializable class XXX does not declare a static final serialVersionUID field of type long
那么什么是serialVersionUID?

序列化操作的时候系统会把当前类的serialVersionUID写入到序列化文件中,当反序列化时系统会去检测文件中的serialVersionUID,判断它是否与当前类的serialVersionUID一致,如果一致就说明序列化类的版本与当前类版本是一样的,可以反序列化成功,否则失败。
当实现java.io.Serializable接口的类没有显式地定义一个serialVersionUID变量时候,Java序列化机制会根据编译的Class自动生成一个serialVersionUID作序列化版本比较用,这种情况下,如果Class文件(类名,方法明等)没有发生变化(增加空格,换行,增加注释等等),就算再编译多次,serialVersionUID也不会变化的。
如果我们不希望通过编译来强制划分软件版本,即实现序列化接口的实体能够兼容先前版本,就需要显式地定义一个名为serialVersionUID,类型为long的变量,不修改这个变量值的序列化实体都可以相互进行串行化和反串行化。

serialVersionUID有两种显示的生成方式:
一是默认的1L,比如:private static final long serialVersionUID = 1L;
二是根据类名、接口名、成员方法及属性等来生成一个64位的哈希字段,比如:
private static final long serialVersionUID = xxxxL;



关于重写的toString方法:与序列化无关,而用于打印对象时显示。如果不重写,则使用父类的toString方法:返回的是一个字符串,它的值等于:getClass().getName() + '@' + Integer.toHexString(hashCode())

你可能感兴趣的:(java)