Java常见疑难问题-应用18


58. Hash集合序列化
class Super implements Serializable{
// HashSet要放置在父类中会百分百机率出现
// 放置到子类中就不一定会出现
final Set set = new HashSet();
}
class Sub extends Super {
private int id;
public Sub(int id) {
this.id = id;
set.add(this);
}
public int hashCode() {
return id;
}
public boolean equals(Object o) {
return (o instanceof Sub) && (id == ((Sub) o).id);
}
}

public class SerialKiller {
public static void 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方法中,请避免直接或间接地在正在进行反序列化的对
象上调用任何方法,因为正在反序列化的对象处于不稳定状态。
59. 迷惑的内部类
public class Twisted {
private final String name;
Twisted(String name) {
this.name = name;
}
// 私有的不能被继承,但能被內部类直接访问
private String name() {
return name;
}
private void reproduce() {
new Twisted(“reproduce”) {
void printName() {
// name()为外部类的,因为没有被继承过来
System.out.println(name());// main
}
}.printName();
}

public static void main(String[] args) {
new Twisted(“main”).reproduce();
}
}

在顶层的类型中,即本例中的Twisted类,所有的本地的、内部的、嵌套的长匿名的类都可
以毫无限制地访问彼此的成员。

另一个原因是私有的不能被继承。

声明: 除非转自他站(如有侵权,请联系处理)外,本文采用 BY-NC-SA 协议进行授权 | 智乐兔
转载请注明:转自《Java常见疑难问题-应用18
本文地址:https://www.zhiletu.com/archives-251.html
关注公众号:智乐兔

赞赏

wechat pay微信赞赏alipay pay支付宝赞赏

上一篇
下一篇

相关文章

在线留言

你必须 登录后 才能留言!

在线客服
在线客服 X

售前: 点击这里给我发消息
售后: 点击这里给我发消息

智乐兔官微