zoukankan      html  css  js  c++  java
  • 双校验 单例类

    package com.example.demo;
    
    import java.io.ObjectStreamException;
    import java.io.Serializable;
    
    public class Person implements Serializable {
    
      private static final long serialVersionUID = 1L;
    
      private volatile static Person singletion;
    
      private Person() {
        if (null == Person.singletion) {
          return;
        } else {
          throw new RuntimeException("单例类不允许二次调用构造函数");
        }
      }
    
      public static Person getSingletion() {
        if (null == Person.singletion) {
          synchronized (Person.class) {
            if (null == Person.singletion) {
              Person.singletion = new Person();
            }
          }
        }
    
        return Person.singletion;
      }
    
    
      private Object readResolve() throws ObjectStreamException {
        return Person.singletion;
      }
    
      protected Object clone() throws CloneNotSupportedException {
        return Person.singletion;
      }
    
    }
    

      volatile 禁止重排序,强制让所有线程缓存失效, 避免了线程获取未构造完全的实例,也避免了线程缓存造成的判 null 问题。构造方法、readResolve、clone 三个方法可以避免反射,反序列化,克隆造成的单例失效。测试代码如下

    public static void main(String[] arg) throws Exception {
        Person person = Person.getSingletion();
        ObjectOutputStream out = new ObjectOutputStream(
            new FileOutputStream("F:\work\IDEA_SPACE\bigdata\demo\src\main\resources\a.txt", true));
        out.writeObject(person);
    
        ObjectInputStream in = new ObjectInputStream(
            new FileInputStream("F:\work\IDEA_SPACE\bigdata\demo\src\main\resources\a.txt"));
        Person person1 = (Person)in.readObject();
    
        log.debug("序列化相等: {}", person == person1);
    
        Person person3 = (Person) person.clone();
        log.debug("克隆相等: {}", person == person3);
    
        Constructor<Person> constructor = Person.class.getDeclaredConstructor();
        constructor.setAccessible(true);
        Person person2 = constructor.newInstance();
    
        log.debug("反射相等: {}", person == person2);
      }
    

      运行结果如下:

    225  [main] DEBUG c.Main - 序列化相等: true
    228  [main] DEBUG c.Main - 克隆相等: true
    Exception in thread "main" java.lang.reflect.InvocationTargetException
    	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    	at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    	at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
    	at com.example.demo.Main.main(Main.java:79)
    Caused by: java.lang.RuntimeException: 单例类不允许二次调用构造函数
    	at com.example.demo.Person.<init>(Person.java:16)
    

      

  • 相关阅读:
    《那些年啊,那些事——一个程序员的奋斗史》——117
    《那些年啊,那些事——一个程序员的奋斗史》——116
    《那些年啊,那些事——一个程序员的奋斗史》——116
    《那些年啊,那些事——一个程序员的奋斗史》——118
    《那些年啊,那些事——一个程序员的奋斗史》——119
    《那些年啊,那些事——一个程序员的奋斗史》——117
    《那些年啊,那些事——一个程序员的奋斗史》——119
    283. Move Zeroes
    26. Remove Duplicates from Sorted Array
    268. Missing Number
  • 原文地址:https://www.cnblogs.com/wudeyun/p/13834692.html
Copyright © 2011-2022 走看看