您的位置:首页 > 编程语言 > Java开发

《Java面向对象编程》学习笔记17--对象的序列化和反序列化

2009-11-11 20:12 411 查看
原文出处:http://blog.csdn.net/gnuhpc/archive/2009/10/24/4722525.aspx

将原文的代码加了main函数

1.定义:

序列化--将对象写到一个输出流中。反序列化则是从一个输入流中读取一个对象。类中的成员必须是可序列化的,而且要实现Serializable接口,这样的类的对象才能被序列化和反序列化。这个接口是一个表示型的接口。serialVersionUID
是一个串行化类的通用标示符,反串行化就是使用这个标示符确保一个加载的类对应一个可串行化的对象。

自己指定了serialVersionUID,就可以在序列化后,去添加一个字段,或者方法,而不会影响到后期的还原,还原后的对象照样可以使用,
而且还多了方法可以用。serialVersionUID的生成,可以写1,也可以写2,但最好还是按照摘要算法,生成一个惟一的指纹数
字,eclipse可以自动生成的,jdk也自带了这个工具。一般写法类似于

private static final long serialVersionUID = -763618247875550322L;

2.序列化步骤:

1)创建一个对象输出流:可以包装一个其他类型的输出流。

2)通过对象输出流的writeObject()写对象。注意使用类型转化,转换为相应的类的对象。

3.反序列化步骤:

1)创建一个对象输入流:可以包装一个其他类型的输出流。

2)通过对象输出流的readObject()写对象。

4.什么对象需要被序列化?

序列化的基本想法是完成对实例信息的保证。因为实例信息在运行结束后就消失了。要储存什么信息呢?一定不是关于方法的信息。

5.使用注意事项:

a.有些属性处于安全考虑不能被序列化(或者不能被序列化),则用transit修饰,若想进一步控制序列化和反序列化,则类中提供
readObject()方法和writeObject()方法,(反)序列化时就会调用自定义的方法。注意这两个方法不是在
java.io.Serializable接口定义的,而是在ObjectInputStream和ObjectOutputStream类中定义的,这
两个类实现ObjectInput 和ObjectOutput两个接口。下边是一个可变数组的例子,取自Java in a Nutshell
2rd Edition,它在串行化实现了高效的针对可变数组程度调整的方法:

public class IntList implements Serializable
{
private static final long serialVersionUID = -6054947246947608649L;
private int[] nums = new int[8]; // An array to store the numbers.
private transient int size = 0; // Index of next unused element ofnums[].
/** Return an element of the array */
public int elementAt(int index) throws ArrayIndexOutOfBoundsException
{
if (index >= size)
throw new ArrayIndexOutOfBoundsException(index);
else
return nums[index];
}
/** Add an int to the array, growing the array if necessary. */
public void add(int x)
{
if (nums.length == size)
resize(nums.length * 2); // Grow array, if needed.
nums[size++] = x; // Store the int in it.
}
/** An internal method to change the allocated size of the array. */
protected void resize(int newsize)
{
int[] oldnums = nums;
nums = new int[newsize]; // Create a new array.
System.arraycopy(oldnums, 0, nums, 0, size); // Copy arrayelements.
}
/** Get rid of unused array elements before serializing the array. */
private void writeObject(ObjectOutputStream out) throws IOException
{
if (nums.length > size)
resize(size); // Compact the array.
out.defaultWriteObject(); // Then write it out normally.
}
/** Compute the transient size field after deserializing the array. */
private void readObject(ObjectInputStream in) throws IOException,
ClassNotFoundException
{
in.defaultReadObject(); // Read the array normally.
size = nums.length; // Restore the transient field.
}
public static void main(String[] args) throws Exception
{
IntList list = new IntList();
for(int i = 0 ; i < 10 ; i++)
{
list.add(i);
}
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);

oos.writeObject(list);
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bais);
IntList list2 = new IntList();
list2 = (IntList)ois.readObject();
for(int i = 0 ;i < 10 ; i++)
{
System.out.println(list2.elementAt(i));
}

}
}


注意:代码中我们自己定义的writeObject()和readObject()是由JVM为我们调用的.

b.由于序列化是针对类的实例,也就是对象的,所以static这样的成员是类相关的,也就不会被序列化。

c.注意,API中一个类一旦被序列化了,那么它的父类都是序列化的。你自己设计的类要是想被序列化,那么其父类要确保都序列化。父类一旦序列化,则子类们都自动实现了序列化。所以内部类和可扩展类不建议序列化。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: