接上回的單例模式線程是否安全?
https://blog.csdn.net/weixin_45262118/article/details/108519818
咱們先來談談枚舉
枚舉是JDK1.5推出的新特性,自己也是一個class類
java
咱們先建立一個枚舉安全
public enum EnumTest { INSTANCE; //寫一個就爲單例 public EnumTest getInstance() { return INSTANCE; } }
枚舉是線程安全的嗎?直接上代碼測試!測試
class SingleTest { public static void main(String[] args) { EnumTest instance1 = EnumTest.INSTANCE; EnumTest instance2 = EnumTest.INSTANCE; System.out.println(instance1); System.out.println(instance2); } }
經過反射的 newInstance 方法的源碼得知 枚舉沒法經過反射建立對象
spa
枚舉沒法用反射建立對象 咱們測試一下
.net
咱們嘗試經過反射枚舉的無參構造建立來建立對象線程
public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException { EnumTest instance1 = EnumTest.INSTANCE; Constructor<EnumTest> declaredConstructor = EnumTest.class.getDeclaredConstructor(null); declaredConstructor.setAccessible(true); EnumTest instance2 = declaredConstructor.newInstance(); System.out.println(instance1); System.out.println(instance2); }
運行 發現報錯了 可是看報的錯誤和咱們預期的不同
並無報出 newInstance 中拋出的異常:
Cannot reflectively create enum objects
而是 拋出了 沒有這樣的方法 的異常
難道是IDEA騙了咱們?爲何不是無參構造方法 拋出沒有這樣的方法的異常?
經過百度查閱資料獲得下面的結論
能夠在上圖中看出實際上是有參構造的 並且參數是String 和 int
一樣的方法經過反射來建立對象
3d
public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException { EnumTest instance1 = EnumTest.INSTANCE; Constructor<EnumTest> declaredConstructor = EnumTest.class.getDeclaredConstructor(String.class,int.class); declaredConstructor.setAccessible(true); EnumTest instance2 = declaredConstructor.newInstance(); System.out.println(instance1); System.out.println(instance2); }
終於獲得了預期的異常!!也就證實了不能經過反射來破壞枚舉單例模式!
code