避免单例模式被反序列化和反射创建出新的实例

双重检测锁的单例模式

package com.nanc;

import java.io.ObjectStreamException;
import java.io.Serializable;

public class Singleton implements Serializable {

    private static final long serialVersionUID = -7357258499538582501L;

    private static volatile Singleton instance;
    private String name;

    private Singleton(){
        //防止使用反射的方式创建实例
        if (null != instance) {
            throw new RuntimeException("");
        }
    }

    private Singleton(String name) {
        //防止使用反射的方式创建实例
        if (null != instance) {
            throw new RuntimeException("");
        }

        System.out.println("调用有参数的构造器");
        this.name = name;
    }

    public static Singleton getInstance(String name) {
        if (null == instance) {
            synchronized(Singleton.class){
                if (null == instance) {
                    instance = new Singleton(name);
                }
            }
        }
        return instance;
    }

    /**
     * 提供readResolve()方法
     *  当JVM反序列化地恢复一个新对象时,
     *  系统会自动调用这个readResolve()方法返回指定好的对象,
     *  从而保证系统通过反序列化机制不会产生多个java对象
     * @return
     * @throws ObjectStreamException
     */
    private Object readResolve()throws ObjectStreamException {
        return instance;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

使用反射获取实例测试

public class SingletonTest {

   public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
      Singleton s = Singleton.getInstance("hello");
      Class cls = Singleton.class;
      Constructor con = cls.getDeclaredConstructor();
      con.setAccessible(true);

      Singleton s2 = (Singleton) con.newInstance();
      System.out.println(s2.getName());

   }
}

使用反序列化获取实例测试

public class SingletonTest {

   public static void main(String[] args) throws IOException {
      Singleton s = Singleton.getInstance("Hello");
      System.out.println("Wolf对象创建完成");

      Singleton s2;

      ObjectOutputStream oos = null;
      ObjectInputStream ois = null;

      try {
         oos = new ObjectOutputStream(new FileOutputStream("a.bin"));
         ois = new ObjectInputStream(new FileInputStream("a.bin"));

         oos.writeObject(s);
         oos.flush();

         TimeUnit.SECONDS.sleep(1);

         //不会调用该类的构造器
         s2 = (Singleton) ois.readObject();

         //是否是同一个对象
         System.out.println(System.identityHashCode(s));
         System.out.println(System.identityHashCode(s2));
      } catch (Exception e) {
         e.printStackTrace();
      }finally {
         if (oos != null) {
            oos.close();
         }
         if (ois != null) {
            ois.close();
         }
      }
   }
}
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容