设计模式之单例模式最佳实现方式 (5)

经过代码分析:三重检测防止不了反射破坏类的唯一性

4.2、第二种办法:红绿灯标识 //修改TCLLazyMan的构造方法为:
private TCLLazyMan(){
   synchronized (TCLLazyMan.class){
       //标识为false,说明之前没有使用TCLLazyMan的构造方法,也就是没有被实例化过
       if (ahfndsjbvnc == false){
           //改变标识
           ahfndsjbvnc = true;
      }else{
           throw new RuntimeException("不要使用反射破坏类的唯一性");
      }
  }
}

//测试
public static void main(String[] args) throws Exception {

   //创建对象1和2,通过反射获得构造方法的newInstance()方法
   Constructor constructor = TCLLazyMan.class.getDeclaredConstructor(null);
   constructor.setAccessible(true);
   TCLLazyMan instance1 = (TCLLazyMan)constructor.newInstance();
   TCLLazyMan instance2 = (TCLLazyMan)constructor.newInstance();
}

/*
结果分析:
Exception in thread "main" java.lang.reflect.InvocationTargetException
Caused by: java.lang.RuntimeException: 不要使用反射破坏类的唯一性

说明这种方法好像可以防止反射创建不同对象
*/

但是如果通过反编译找到了设置标识的参数,并且修改了它的值呢?

public static void main(String[] args) throws Exception {

   //创建对象1和2,通过反射获得构造方法的newInstance()方法
   Constructor constructor = TCLLazyMan.class.getDeclaredConstructor(null);
   constructor.setAccessible(true);

   //通过反射获得设置标识的属性
   Field field = TCLLazyMan.class.getDeclaredField("ahfndsjbvnc");
   field.setAccessible(true);

   TCLLazyMan instance1 = (TCLLazyMan)constructor.newInstance();
   
   //改变属性的值
   field.set(instance1,false);

   TCLLazyMan instance2 = (TCLLazyMan)constructor.newInstance();

   ////输出结果:instance1和instance2相等吗? false
   System.out.println("instance1和instance2相等吗? " + (instance1 == instance2));
}

/*
结果分析:
设置红绿灯标识防止不了反射破坏类的唯一性
*/

经过代码分析:设置红绿灯标识防止不了反射破坏类的唯一性

4.3、第三种方法:通过枚举类型

进入newInstance()的源码

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpjjjp.html