java序列化是一个常用的手段,即将一些内容保存下来(所谓的数据持久化),以供后续读取。
常用的方式一般应该是
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("path"));
AClass a = new AClass();
String s = "123";
out.writeObject(a);
out.writeObject(s);
out.flush();
out.close();
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("path"));
AClass a2 = (AClass) ois.readObject();
String s2 = (String) ois.readObject();
ois.close();
但今天在测试一个代码时,发现在写入一个类A到文件后在读取时,类A中的一个变量(也是类)一直读不到(为null),研究了很久,才发现是在类A中具有方法如下:
private void writeObject(ObjectOutputStream out) throws IOException
{
out.writeInt(size);
out.writeObject(base);
out.writeObject(check);
}
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException
{
size = in.readInt();
base = (IntArrayList) in.readObject();
check = (IntArrayList) in.readObject();
// charMap = new Utf8CharacterMapping();
}
可以看到,在readObject里charMap被注释掉了。注意,这里也是一个有点阴差阳错的地方:
问题就在于上面这一段代码,并不会直接报错,而是到用到charMap时才会报出nullException,弄得找bug找了好久。
再回到原来的问题,刚开始时是通过很笨的方法(具体就不说了,反正是各种测试、修改、删减)找到是这段代码的问题,但不是很明白,因为此方法并不是重写方法,而且原始的read/writeObject是ObjectStream的方法,不是很懂这段代码为什么起作用。通过查找相关内容,在这里深入JAVA序列化反序列化找到了答案。
简单来说:
同时,文章中还介绍了许多其他的相关内容,值得一读,比如使用transient声明不序列化(static也不序列化)
class Employee implements Serializable {
public String name;
public String address;
//该属性为不可序列化的,所以声明为短暂的
public transient int SSN;
public Number number;
}
serialVersionUID的定义方式
private static final long serialVersionUID = -6849794470754667710L;
以及一些更深层次的源码级探索。
这篇博客java序列化的内部实现对object的过程做了比较详细的阐述。