经过代码分析:三重检测防止不了反射破坏类的唯一性
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()的源码