从前有一个人,他认为世上只有一只不寻常的狗,所以他写出了如下的类,将它作为一个单件(singleton)[Gamma95]: public class Dog extends Exception { public static final Dog INSTANCE = new Dog(). private Dog() {} public String toString(){ return "Woof". } }
结果证明这个人的做法是错误的。你能够在这个类的外部不使用反射来创建出第2个Dog实例吗? 这个类可能看起来像一个单件,但它并不是。问题在于,Dog扩展了Exception,而Exception实现了java.io.Serializable。这就意味着Dog是可序列化的(serializable),并且解序列(deserialization)会创建一个隐藏的构造器。正如下面的这段程序所演示的,如果你序列化了Dog.INSTANCE,然后对得到的字节序列(byte sequence)进行解序列,最后你就会得到另外一个Dog。该程序打印的是false,表示新的Dog实例和原来的那个实例是不同的,并且它还打印了Woof,说明新的Dog实例也具有相应的功能: import java.io.*. public class CopyDog{ // Not to be confused with copycat public static void main(String[] args){ Dog newDog = (Dog) deepCopy(Dog.INSTANCE). System.out.println(newDog == Dog.INSTANCE). System.out.println(newDog). }
// This method is very slow and generally a bad idea! 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). } } }