单例模式再讨论(有关序列化的单例问题)

 class Dog implements Serializable{

   public static final Dog INSTANCE = new Dog();

   private Dog(){}

  }

 上面能控制只生成一个单实例吗?

 如果对实现了Serializable的对象进行序列化后,再反序列化,内中会不只一个实例了,因为反序列化时会重新

 生成一个对象。

 既然INSTANCE为静态域,那序列化时返回的对象如果也是INSTANCE就可以解决问题了,而打开API我们发现

 Serializable接口确实有这样两个特殊的方法描述:

 ? 将对象写入流时需要指定要使用的替代对象的可序列化类,应使用准确的签名来实现此特殊方法:

 ANY-ACCESS-MODIFIER Object writeReplace() throws ObjectStreamException;

 此 writeReplace 方法将由序列化调用,前提是如果此方法存在,而且它可以通过被序列化对象的类中定义的一

 个方法访问。因此,该方法可以拥有私有 (private)、受保护的 (protected) 和包私有 (package-private) 访

 问。子类对此方法的访问遵循 java 访问规则。

 ? 在从流中读取类的一个实例时需要指定替代的类应使用的准确签名来实现此特殊方法:

 ANY-ACCESS-MODIFIER Object readResolve() throws ObjectStreamException;

 此 readResolve 方法遵循与 writeReplace 相同的调用规则和访问规则。

 上述两个方法的只要出现,就会履盖以下两个方法(这两个方法本质的意义就是用来替换序列与反序列的对

 象),虽然会执行它们,但最后得到的结果却是writeReplace、readResolve两个方法写入或读出的对象:

  ? private void writeObject(java.io.ObjectOutputStream out) throws IOException

  ? private void readObject(java.io.ObjectInputStream in)throws IOException, ClassNotFoundException;

 另外,writeObject与readObject需成对实现,而writeReplace与readResolve则不需要成对出现,一般单独使

 用。如果同时出现这四个方法,最后写入与读出的结果以writeReplace和readResolve方法的结果为准。

 所以下要解决真真单实例问题,我们如下修正:

class Dog implements Serializable { 

    public static final Dog INSTANCE = new Dog(); 

    private Dog() {} 

    private Object readResolve() { 

     return INSTANCE; 

    } 

  } 

  public class SerialDog { 

    public static void main(String[] args) throws IOException, 

      ClassNotFoundException { 

     ByteArrayOutputStream bos = new ByteArrayOutputStream(); 

     new ObjectOutputStream(bos).writeObject(Dog.INSTANCE); 

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

     Dog dog = (Dog) new ObjectInputStream(bin).readObject(); 

     System.out.println(dog == Dog.INSTANCE);//true 

    } 

  } 

 一个实现了Serializable的单例类,必须有一个readResolve方法,用以返回它的唯一实例。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值