java集合序列化异常,Java Hash集合序列化问题

classSuperimplements Serializable{

// HashSet要放置在父类中会百分百机率出现

// 放置到子类中就不一定会出现问题了

final Set set = new HashSet();

}

classSubextends Super {

privateint id;

public Sub(int id) {

this.id = id;

set.add(this);

}

publicint hashCode() {

return id;

}

publicboolean equals(Object o) {

return (o instanceof Sub) && (id == ((Sub) o).id);

}

}

publicclass SerialKiller {

publicstaticvoid main(String[] args) throws Exception {

Sub sb = new Sub(888);

System.out.println(sb.set.contains(sb));// true

ByteArrayOutputStream bos = new ByteArrayOutputStream();

new ObjectOutputStream(bos).writeObject(sb);

ByteArrayInputStream bin = new ByteArrayInputStream(bos.toByteArray());

sb = (Sub) new ObjectInputStream(bin).readObject();

System.out.println(sb.set.contains(sb));// false

}

}

Hash一类集合都实现了序列化的writeObject()与readObject()方法。这里错误原因是由HashSet的readObject方法引起的。在某些情况下,这个方法会间接地调用某个未初始化对象的被覆写的方法。为了组装正在反序列化的HashSet,HashSet.readObject调用了HashMap.put方法,而put方法会去调用键的hashCode方法。由于整个对象图正在被反序列化,并没有什么可以保证每个键在它的hashCode方法被调用时已经被完全初始化了,因为HashSet是在父类中定义的,而在序列化HashSet时子类还没有开始初始化(这里应该是序列化)子类,所以这就造成了在父类中调用还没有初始完成(此时id为0)的被子类覆写的hashCode方法,导致该对象重新放入hash表格的位置与反序列化前不一样了。hashCode返回了错误的值,相应的键值对条目将会放入错误的单元格中,当id被初始化为888时,一切都太迟了。

这个程序的说明,包含了HashMap的readObject方法的序列化系统总体上违背了不能从类的构造器或伪构造器(如序列化的readObject)中调用可覆写方法的规则。

如果一个HashSet、Hashtable或HashMap被序列化,那么请确认它们的内容没有直接或间接地引用它们自身,即正在被序列化的对象。

另外,在readObject或readResolve方法中,请避免直接或间接地在正在进行反序列化的对象上调用任何方法,因为正在反序列化的对象处于不稳定状态。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值