当两个进程在进行远程通信时,无论是何种类型的数据,都会以二进制序列的形式在网络上传送。发送方需要把这个Java对象转换为字节序列,才能在网络上传送,称为对象的序列化;接收方则需要把字节序列再恢复为Java对象,称为对象的反序列化。 只有实现了Serializable和Externalizable接口的类的对象才能被序列化,而Externalizable接口又继承自Serializable接口。下面是序列化和外部化接口代码:
1 public interface Serializable {}
2 public interface Externalizable extends Serializable {
void readExternal(ObjectInput in);
void writeExternal(ObjectOutput out);
}
下面是Serializable实现:
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.Date;
public class SerializabeTest {
public static void main(String[] args) throws Exception{
// TODO Auto-generated method stub
ObjectOutputStream out=new ObjectOutputStream(new FileOutputStream("shit.obj"));
Customer customer=new Customer("Gefforey",23);
out.writeObject("Hello,gefforey");
out.writeObject(new Date( ));
out.writeObject(customer);
out.writeInt(520);
out.close();
ObjectInputStream in=new ObjectInputStream(new FileInputStream("shit.obj"));
System.out.println("obj1="+(String)in.readObject());
System.out.println("obj2="+(Date)in.readObject());
System.out.println("obj3:"+(Customer)in.readObject());
System.out.println("obj4="+in.readInt());
in.close();
}
}
class Customer implements Serializable{
public String name;
public int age;
public Customer(String name,int age){
this.name=name;
this.age=age;
}
public String toString(){
return "name="+name+",age="+age+".";
}
}
返回结果:obj1=Hello,gefforey
obj2=Wed Sep 19 23:03:10 CST 2007
obj3:name=Gefforey,age=23.
obj4=520
下面是Externalizable实现:
import java.io.*;
class Test implements Externalizable{ //Test类必须实现Externalizable接口
private String letterstates = "gefforey";
private int num = 0;
public Test(){
}
public void writeExternal(ObjectOutput out) throws IOException {
out.writeObject(letterstates);
out.write(88); //在序列化的数据最后加个88
}
public void readExternal(ObjectInput in) throws IOException,
ClassNotFoundException {
letterstates = (String)in.readObject();
num = in.read(); //把数字88加进来
}
public void printOut(){ //测试
System.out.println(letterstates +num);
}
}
public class AppTest {
private void saveGame(){
Test m = new Test();
if (m != null){
try{
FileOutputStream ostream = new FileOutputStream("t.txt");
ObjectOutputStream p = new ObjectOutputStream(ostream);
p.writeObject(m); //writeExternal()自动执行
p.flush();
ostream.close();
} catch (IOException ioe) {
System.out.println ("Error saving file:");
System.out.println (ioe.getMessage());
}
}
}
private void loadGame(){
try{
FileInputStream instream = new FileInputStream("t.txt");
ObjectInputStream p = new ObjectInputStream(instream);
Test m = (Test)p.readObject();//readExternal()自动执行
m.printOut();
instream.close();
} catch (Exception e) {
System.out.println ("Error loading file:");
System.out.println (e.getMessage());
}
}
public static void main(String[] args){
new AppTest().saveGame();
new AppTest().loadGame();
}
}
运行结果为:gefforey88。
序列化会自动存储必要的信息,用以反序列化被存储的实例,而外部化则只保存被存储的类的标识。当你通过java.io.Serializable接口序列化一个对象时,有关类的信息,比如它的属性和这些属性的类型,都与实例数据一起被存储起来。在选择走Externalizable这条路时,Java 只存储有关每个被存储类型的非常少的信息。
每个接口的优点和缺点
Serializable接口
· 优点:内建支持
· 优点:易于实现
· 缺点:占用空间过大
· 缺点:由于额外的开销导致速度变比较慢
Externalizable接口
· 优点:开销较少(程序员决定存储什么)
· 优点:可能的速度提升
· 缺点:虚拟机不提供任何帮助,也就是说所有的工作都落到了开发人员的肩上。
在两者之间如何选择要根据应用程序的需求来定。Serializable通常是最简单的解决方案,但是它可能会导致出现不可接受的性能问题或空间问题;在出现这些问题的情况下,Externalizable可能是一条可行之路。