Java对对象的序列化的支持很简单,只要涉及的类和本类实现了java.io.Serializable接口,有一个serialVersionUID 就可以利用java.io.ObjectOutputStream进行对象的二进制格式输出了:
package objOutPut;

import java.io.*;

import java.util.Hashtable;
import java.util.ArrayList;


public class Canvas implements Serializable ...{
private static final long serialVersionUID = -8391639048829504801L;

public Hashtable htLabels = null;

public ArrayList alLabels = null;


public Canvas() ...{
htLabels = new Hashtable();
alLabels = new ArrayList();
}

public void toFile(String fileSpec) throws FileNotFoundException,

IOException ...{
ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream(
fileSpec));
os.writeObject(this);
}

public Canvas fromFile(String fileSpec) throws FileNotFoundException,

IOException, ClassNotFoundException ...{
ObjectInputStream is = new ObjectInputStream(new FileInputStream(
fileSpec));
return (Canvas) is.readObject();

}
}
现在问题是:在上述这个类里面,含有2个容器:Hashtable和ArrayList。如他们都同时保存了对象o(我们知道容器只是拷贝保存对象的指针),在序列化的时候,会不会把o存2次呢?感觉起来应该是只保存一次。可是不敢确定,于是验证了下:
在同一个包里面,定义了一个Label类,他的实例会被放在上述容器中,
package objOutPut;


public class Label implements java.io.Serializable...{
private static final long serialVersionUID = -4343239993805802185L;
public int id;
public String name;
public Point labelPoint;

public Label(int id, String name, Point labelPoint)...{
this.id = id;
this.name =name;
this.labelPoint = labelPoint;
}

public Label(int id, String name, double x, double y)...{
this(id, name, new Point(x,y));
}
}

这里还用到了Point类,一个超级简单的类,又是超级有用的类:
package objOutPut;


public class Point implements java.io.Serializable ...{
private static final long serialVersionUID = 6582745579823418928L;
public double x;
public double y;

public Point(double x, double y)...{
this.x = x;
this.y = y;
}
}

后面定义的2个类都是Serializable的,而且都有serialVersionUID。那么现在我们在Canvas里面加入Label类的实例,然后导出到文件,然后在导入,看内存地址指的对象是否还是同一个:
在Canvas中加入main方法:

public static void main(String[] argus) ...{
Canvas c = new Canvas();
Label label1 = new Label(1, "1", 1, 1);
Label label2 = new Label(2, "2", 2, 2);

c.htLabels.put("1", label1);
c.htLabels.put("2", label2);

c.alLabels.add(label1);
c.alLabels.add(label2);

try ...{
c.toFile("C:/Canvas.out");

} catch (FileNotFoundException e) ...{
// TODO Auto-generated catch block
e.printStackTrace();

} catch (IOException e) ...{
// TODO Auto-generated catch block
e.printStackTrace();
}

try ...{
Canvas cc = c.fromFile("C:/Canvas.out");
System.out.println(cc.htLabels.size());

} catch (FileNotFoundException e) ...{
// TODO Auto-generated catch block
e.printStackTrace();

} catch (IOException e) ...{
// TODO Auto-generated catch block
e.printStackTrace();

} catch (ClassNotFoundException e) ...{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
在Eclipse3.2下设置断点,观察CC中Hashtable和ArrayList中保存的Label实例的内存ID,同时也观察他们包含的Point的内存ID。发现是一样的。
结论:序列化时,即便容器包含2份对象指针,实际只会出现一个实例被序列化了。这个跟java容器本身保存对象指针是一致的。C++的Vector确是保存对象的拷贝了,而且是深拷贝。