Java 的对象序列化将那些实现了Serializable 接口的对象转换成一个字节序列, 并能够在以后将这个字节序列完全恢复为原来的对象. 这一过程可以在网络进行, 这意味着序列化机制能自动弥补不同操作系统之间的差异.
对象序列化的概念是RMI,EJB 等技术的基础.
很多标准类库都实现了序列化机制, 包括所有的基础数据类型的封装器, 所有容器类以及很多其他的东西. 甚至Class 对象也可以被序列化.
序列化与反序列化的方法:
要序列化一个对象A, 首先要创建ObjectInputStream 对象, 然后writeObject 对象A, 恢复对象A 的时候创建ObjectOutputStream 对象, 然后readObject 得到对象A.
对Serializable 对象来说, 对象完全以它存储的二进制位为基础来构造, 而不是调用构造器. 而对于一个Externalizable 对象, 恢复对象的时候, 所有普通的默认构造器都会被调用, 然后再调用readExternal().
Externalizable 接口:
实例: 该接口中有两个方法, 在序列化与反序列化的时候使用, 而不是调用ObjectInputStream 与ObjectOutputStream 中的方法.
清单1: User
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
public class User implements Externalizable
{
private static final long serialVersionUID = 1L;
private int id ;
private String name ;
private String password ;
public User()
{
System. out .println( " 默认构造方法" );
}
public User( int id, String name, String password)
{
this . id = id;
this . name = name;
this . password = password;
System. out .println( " 有参构造方法" );
}
public int getId()
{
return id ;
}
public void setId( int id)
{
this . id = id;
}
public String getName()
{
return name ;
}
public void setName(String name)
{
this . name = name;
}
public String getPassword()
{
return password ;
}
public void setPassword(String password)
{
this . password = password;
}
public void readExternal(ObjectInput objectInput) throws IOException,
ClassNotFoundException
{
System. out .println( " 读" );
id = (Integer) objectInput.readObject();
name = (String)objectInput.readObject();
password = (String)objectInput.readObject();
}
public void writeExternal(ObjectOutput objectOutput) throws IOException
{
System. out .println( " 写" );
System. out .println( id );
objectOutput.writeObject( id );
objectOutput.writeObject( name );
objectOutput.writeObject( password );
}
}
要序列化的对象一定要确保自己的父类能够建立成功, 即父类有无参构造方法.
Transient 关键字
对于一个serializable 来说, 如果不想让某个字段进行序列化的话, 则对该字段加上Transient, 则该字段不会序列化.
由于Externalizable 对象在默认情况下不保存他们的任何字段, 所以Transient 关键字只能和Serializable 对象一起使用.
Externalizable 的替代方法( 最好的方法)
在实现serializable 接口的对象中, 添加writeObject() 与readObject() 方法.
这样一旦对象被序列化或者反序列化还原, 就会自动的分别调用这两个方法, 只要提供这两个方法, 就会使用他们而不是默认的序列化机制.
这些方法必须有准确的方法特征签名:
private void readObject(ObjectInputStream objectInput) throws IOException,
ClassNotFoundException
{
objectInput.defaultReadObject();
}
private void writeObject(ObjectOutputStream objectOutput) throws IOException
{
objectOutput.defaultWriteObject();
} 在调用ObjectOutputStream.writeObject(), 会检查所传递的Serializable 对象, 看看是否实现了自己的writeObject(), 如果是这样, 就跳过正常的序列化过程并调用它的witeObject
在自己的writeObject(), 我们可以调用defaultWriteObject 方法来执行默认的witeObject(), 就是执行序列化机制.