利用反射機制破壞了單例模式,這裏以懶漢單例模式爲例子進行操做。
以前利用反射也是改變了類中的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封裝和反射等的理解。
相信能從你們的評論中學會不少。