『Effective Java 第3版』と『Java Puzzlers』ー パズル91 ー
『Effective Java 第3版』の「項目88 防御的に
readObject
メソッドを書く」で言及されているのがパズル91です。
パズル91 連続殺人犯(Serial Killer)
このプログラムは、オブジェクトを生成して、それがクラスの不変式に従っているかを検査しています。それから、プログラムはオブジェクトをシリアライズして、ディシリアライズし、そして、そのディシリアライズしたコピーもその不変式に従っているかを検査しています。 従っていますか? 従っていないとしたら、なぜですか?
import java.util.*;
import java.io.*;
public class SerialKiller {
public static void main(String[] args) {
Sub sub = new Sub(666);
sub.checkInvariant();
Sub copy = (Sub) deepCopy(sub);
copy.checkInvariant();
}
// シリアライズで引数をコピー(パズル80参照)
static public Object deepCopy(Object obj) {
try {
ByteArrayOutputStream bos =
new ByteArrayOutputStream();
new ObjectOutputStream(bos).writeObject(obj);
ByteArrayInputStream bin =
new ByteArrayInputStream(bos.toByteArray());
return new ObjectInputStream(bin).readObject();
} catch(Exception e) {
throw new IllegalArgumentException(e);
}
}
}
class Super implements Serializable {
final Setset = new HashSet ();
}
final class Sub extends Super {
private int id;
public Sub(int id) {
this.id = id;
set.add(this); // 不変式の確立
}
public void checkInvariant() {
if (!set.contains(this))
throw new AssertionError("invariant violated");
}
public int hashCode() {
return id;
}
public boolean equals(Object o) {
return (o instanceof Sub) && (id == ((Sub)o).id);
}
}
この記事へのコメント