您的位置:首页 > 理论基础 > 计算机网络

ArrayList的remove、序列化(二)

2016-07-11 15:40 399 查看
对象的序列化作为一种存储对象为字节序列的方式,可以将对象保存到本地文件或者通过网络进行传输,是RMI对象或参数传递的基础。

对象的序列化会在输出流中保留一个序列化编号,当再次通过该对象输出流对同一个对象进行序列化时,只会存储一个编号,而不会存储整个对象。这种方式虽然可以保证在执行反序列化时,得到的仍然是同一个对象,但是同样使得第一次序列化后,对对象执行的修改在后续序列化中得不到保存,当然前提是使用同一个对象输出流,如果新建了输出流,则理所应当存储对象。

示例:

class t2{
public static void main(String[] args){
Person p=new Person("xiaoming",18);
ObjectOutputStream os=null;
ObjectInputStream oi=null;
try{
os=new ObjectOutputStream(new FileOutputStream("t1.txt"));
os.writeObject(p);//第一次序列化
p.name="zhangsan";//方便起见,属性直接为public
os.writeObject(p);//第二次序列化
oi=new ObjectInputStream(new FileInputStream("t1.txt"));

Person p1=(Person)oi.readObject();
System.out.println("p1:"+p1);
Person p2=(Person)oi.readObject();
System.out.println("p2:"+p2);
System.out.println("p2==p1:"+(p2==p1));
}catch(Exception e){
e.printStackTrace();
}finally{
try{
if(os!=null){
os.close();
}
}catch(IOException e){
e.printStackTrace();
}
}
}
}

class Person implements Serializable{
public String name;
public int age;
public Person(String name,int age){
this.name=name;
this.age=age;
}
public String toString(){
return "name:"+name+",age:"+age;
}
}
/*
*输出结果为:
*p1:name:xiaoming,age:18
*p2:name:xiaoming,age:18
*p2==p1:true
*/
对象的修改没有得到保存。

这里多说一句,待执行序列化的对象,其类必须实现了序列化接口,并且其内部属性,如果没有显式加transient修饰,则属性的类也必须实现序列化接口,该示例String,Number类都实现了序列化接口,否则会抛出NotSerializableException。

关于ArrayList的序列化操作

ArrayList的属性表示为:

private static final long serialVersionUID = 8683452581122892189L;
private transient Object[] elementData;
private int size;
其中将elementData元素数组加以transient修饰,表示在ArrayList对象的序列化时,忽略数组的序列化。在ArrayList内部存在writeObject方法

private void writeObject(java.io.ObjectOutputStream s)
throws java.io.IOException{
// Write out element count, and any hidden stuff
int expectedModCount = modCount;
s.defaultWriteObject();

// Write out array length
s.writeInt(elementData.length);

// Write out all elements in the proper order.
for (int i=0; i<size; i++)
s.writeObject(elementData[i]);

if (modCount != expectedModCount) {
throw new ConcurrentModificationException();
}

}
意思也就是在ArrayList对象序列化时,关于elementData元素数组部分的序列化的控制权,由ObjectOutputStream转移给ArrayList对象本身来控制。

elementData是一个Object[]类型的数组,数组的容量大小是动态扩展的,最初为10,size反映的是有效表示的元素个数,从代码中可以看到,对于elementData数组的元素,进行序列化的只是有效的数据元素,而非elementData数组的全部容量。

示例:

class t2{
public static void main(String[] args){
T_list<String> list=new T_list(10);
list.add("first");
list.add("second");
ObjectOutputStream os=null;
ObjectInputStream oi=null;
try{
os=new ObjectOutputStream(new FileOutputStream("t1.txt"));

os.writeObject(list);

oi=new ObjectInputStream(new FileInputStream("t1.txt"));

T_list<String> list1=(T_list<String>)oi.readObject();

}catch(Exception e){
e.printStackTrace();
}finally{
try{
if(os!=null){
os.close();
}
}catch(IOException e){
e.printStackTrace();
}
}
}
}

class T_list<E> implements Serializable{
private transient Object[] elementData;
private int size;
public T_list(int capacity){
this.elementData=new Object[capacity];
size=0;
}
public void add(E e){
if(size==elementData.length){
throw new IndexOutOfBoundsException();
}
elementData[size++]=e;
}
public int getElementsLength(){
return elementData.length;
}
private void writeObject(java.io.ObjectOutputStream s) throws Exception{
// Write out element count, and any hidden stuff

s.defaultWriteObject();

// Write out array length
s.writeInt(elementData.length);

// Write out all elements in the proper order.
for (int i=0; i<size; i++){
s.writeObject(elementData[i]);
}
}
private void readObject(java.io.ObjectInputStream s) throws Exception{
// Read in size, and any hidden stuff
s.defaultReadObject();

// Read in array length and allocate array
int arrayLength = s.readInt();
Object[] a = elementData = new Object[arrayLength];

// Read in all elements in the proper order.
for (int i=0; i<size; i++){
a[i] = s.readObject();
}
}
}

总结:

对象的序列化会在输出流中保存一个对象的序列化编号,防止重复对一个对象进行多次保存,例如多个对象包含对同一个对象的引用,在序列化时只保存一次该引用对象。也避免了反序列化时,对同一个引用生成多个不同的对象。但是造成了在一次序列化之后,对象上的修改不能在再次序列化时保存。

ArrayList的elementData元素数组使用transient修饰,在ArrayList对象进行序列化时,将忽略该部分,由ArrayList对象控制对elementData的序列化和反序列化,依次保证只对数组有效元素部分进行序列化。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息