利用反射机制破坏了单例模式,这里以懒汉单例模式为例子进行操做。
以前利用反射也是改变了类中的private变量。
类中的private变量真的private么?java
这里采用了懒汉的单例模式,顺带说一句我本身对懒汉饿汉的理解:
懒汉就是在类加载的时候并不建立对象的实例,在你用到的时候才去建立一个实例。
饿汉就是无论你用不用到,这个类加载的时候就建立了一个实例。用到的时候就返回那个已经建立好的实例。
根本的区别在于建立实例的时机不一样。segmentfault
单例模式的类:测试
public class SingleTest { private static SingleTest singleTest; private SingleTest(){} public static SingleTest getSingleTest() { if(singleTest==null) { singleTest = new SingleTest(); } return singleTest; } }
测试类:code
import java.lang.reflect.Field; public class Test { public static void main(String args[]) { SingleTest s1 = SingleTest.getSingleTest(); SingleTest s2 = SingleTest.getSingleTest(); System.out.println("s1 hashCode: "+s1.hashCode()); System.out.println("s2 hashCode: "+s2.hashCode()); } }
这个类中我打印了s1和s2的hashCode用来验证是否是同一个对象。
输出以下:对象
s1 hashCode: 2943240 s2 hashCode: 2943240
能够看到s1和s2实际上是同一个实例。get
单例模式的类仍然不变。hash
测试类以下:io
import java.lang.reflect.Constructor; import java.lang.reflect.Field; public class Test { public static void main(String args[]) { SingleTest s1 = SingleTest.getSingleTest(); SingleTest s2 = SingleTest.getSingleTest(); SingleTest s3 = null; System.out.println("s1 hashCode: "+s1.hashCode()); System.out.println("s2 hashCode: "+s2.hashCode()); Class singleClass = s1.getClass(); try { Constructor constructor = singleClass.getDeclaredConstructor(); constructor.setAccessible(true); s3 = (SingleTest) constructor.newInstance(); } catch (Exception e) { e.printStackTrace(); } System.out.println("s3 hashCode: "+s3.hashCode()); } }
输出结果以下:class
s1 hashCode: 18262862 s2 hashCode: 18262862 s3 hashCode: 28420709
能够看到s3和s1s2已经不是同一个实例了。import
就这样,成功的破坏了单例模式。
仍是同样,但愿听到你们对java封装和反射等的理解。
相信能从你们的评论中学会不少。