午夜剧场伦理_日本一道高清_国产又黄又硬_91黄色网战_女同久久另类69精品国产_妹妹的朋友在线

您的位置:首頁技術(shù)文章
文章詳情頁

JAVA破壞單例模式的方式以及避免方法

瀏覽:12日期:2022-08-31 08:51:36

單例模式,大家恐怕再熟悉不過了,其作用與實(shí)現(xiàn)方式有多種,這里就不??鋁恕5?牽?勖竊謔褂謎廡┓絞絞迪值ダ?J絞保?絳蛑芯駝嫻幕嶂揮幸桓鍪道?穡?/p>

聰明的你看到這樣的問話,一定猜到了答案是NO。這里筆者就不賣關(guān)子了,開門見山吧!實(shí)際上,在有些場(chǎng)景下,如果程序處理不當(dāng),會(huì)無情地破壞掉單例模式,導(dǎo)致程序中出現(xiàn)多個(gè)實(shí)例對(duì)象。

下面筆者介紹筆者已知的三種破壞單例模式的方式以及避免方法。

1、反射對(duì)單例模式的破壞

我們先通過一個(gè)例子,來直觀感受一下

(1)案例

DCL實(shí)現(xiàn)的單例模式:

public class Singleton{ private static volatile Singleton mInstance; private Singleton(){} public static Singleton getInstance(){ if(mInstance == null){ synchronized (Singleton.class) {if(mInstance == null){ mInstance = new Singleton();} } } return mInstance; }}

測(cè)試代碼:

public class SingletonDemo { public static void main(String[] args){ Singleton singleton = Singleton.getInstance(); try { Constructor<Singleton> constructor = Singleton.class.getDeclaredConstructor(); constructor.setAccessible(true); Singleton reflectSingleton = constructor.newInstance(); System.out.println(reflectSingleton == singleton); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } }}

執(zhí)行結(jié)果:

false

運(yùn)行結(jié)果說明,采用反射的方式另辟蹊徑實(shí)例了該類,導(dǎo)致程序中會(huì)存在不止一個(gè)實(shí)例。

(2)解決方案

其思想就是采用一個(gè)全局變量,來標(biāo)記是否已經(jīng)實(shí)例化過了,如果已經(jīng)實(shí)例化過了,第二次實(shí)例化的時(shí)候,拋出異常。實(shí)現(xiàn)代碼如下:

public class Singleton{ private static volatile Singleton mInstance; private static volatile boolean mIsInstantiated = false; private Singleton(){ if (mIsInstantiated){ throw new RuntimeException('Has been instantiated, can not do it again!'); } mIsInstantiated = true; } public static Singleton getInstance(){ if(mInstance == null){ synchronized (Singleton.class) {if(mInstance == null){ mInstance = new Singleton();} } } return mInstance; }}

執(zhí)行結(jié)果:

JAVA破壞單例模式的方式以及避免方法

2、clone()對(duì)單例模式的破壞

當(dāng)需要實(shí)現(xiàn)單例的類允許clone()時(shí),如果處理不當(dāng),也會(huì)導(dǎo)致程序中出現(xiàn)不止一個(gè)實(shí)例。

(1)案例

一個(gè)實(shí)現(xiàn)了Cloneable接口單例類:

public class Singleton implements Cloneable{ private static volatile Singleton mInstance; private Singleton(){ } public static Singleton getInstance(){ if(mInstance == null){ synchronized (Singleton.class) {if(mInstance == null){ mInstance = new Singleton();} } } return mInstance; } @Override protected Object clone() throws CloneNotSupportedException { // TODO Auto-generated method stub return super.clone(); }}

測(cè)試代碼:

public class SingletonDemo { public static void main(String[] args){ try { Singleton singleton = Singleton.getInstance(); Singleton cloneSingleton; cloneSingleton = (Singleton) Singleton.getInstance().clone(); System.out.println(cloneSingleton == singleton); } catch (CloneNotSupportedException e) { e.printStackTrace(); } }}

執(zhí)行結(jié)果:

false

(2)解決方案:

解決思想是,重寫clone()方法,調(diào)clone()時(shí)直接返回已經(jīng)實(shí)例的對(duì)象

public class Singleton implements Cloneable{ private static volatile Singleton mInstance; private Singleton(){ } public static Singleton getInstance(){ if(mInstance == null){ synchronized (Singleton.class) {if(mInstance == null){ mInstance = new Singleton();} } } return mInstance; } @Override protected Object clone() throws CloneNotSupportedException { return mInstance; }}

執(zhí)行結(jié)果:

true

3、序列化對(duì)單例模式的破壞

在使用序列化/反序列化時(shí),也會(huì)出現(xiàn)產(chǎn)生新實(shí)例對(duì)象的情況。

(1)案例

一個(gè)實(shí)現(xiàn)了序列化接口的單例類:

public class Singleton implements Serializable{ private static volatile Singleton mInstance; private Singleton(){ } public static Singleton getInstance(){ if(mInstance == null){ synchronized (Singleton.class) {if(mInstance == null){ mInstance = new Singleton();} } } return mInstance; }}

測(cè)試代碼:

public class SingletonDemo { public static void main(String[] args){ try { Singleton singleton = Singleton.getInstance(); FileOutputStream fos = new FileOutputStream('singleton.txt'); ObjectOutputStream oos = new ObjectOutputStream(fos); oos.writeObject(singleton); oos.close(); fos.close(); FileInputStream fis = new FileInputStream('singleton.txt'); ObjectInputStream ois = new ObjectInputStream(fis); Singleton serializedSingleton = (Singleton) ois.readObject(); fis.close(); ois.close(); System.out.println(serializedSingleton==singleton); } catch (Exception e) { e.printStackTrace(); } }}

運(yùn)行結(jié)果:

false

(2)解決方案

在反序列化時(shí)的回調(diào)方法 readResolve()中返回單例對(duì)象。

public class Singleton implements Serializable{ private static volatile Singleton mInstance; private Singleton(){ } public static Singleton getInstance(){ if(mInstance == null){ synchronized (Singleton.class) {if(mInstance == null){ mInstance = new Singleton();} } } return mInstance; } protected Object readResolve() throws ObjectStreamException{ return mInstance; }}

結(jié)果:

true

以上就是筆者目前已知的三種可以破壞單例模式的場(chǎng)景以及對(duì)應(yīng)的解決辦法,讀者如果知道還有其他的場(chǎng)景,記得一定要分享出來噢,正所謂“獨(dú)樂樂不如眾樂樂”!!!

單例模式看起來是設(shè)計(jì)模式中最簡(jiǎn)單的一個(gè),但“麻雀雖小,五臟俱全”,其中有很多細(xì)節(jié)都是值得深究的。即便是本篇介紹的這幾個(gè)場(chǎng)景,也只是介紹了一些梗概而已,很多細(xì)節(jié)還需要讀者自己去試驗(yàn)和推敲的,比如:通過枚舉方式實(shí)現(xiàn)單例模式,就不存在上述問題,而其它的實(shí)現(xiàn)方式似乎都存在上述問題!

后記

本篇參(剽)考(竊)了如下資料:https://www.jb51.net/article/143047.htm

以上就是JAVA破壞單例模式的方式以及避免方法的詳細(xì)內(nèi)容,更多關(guān)于JAVA 單例模式的資料請(qǐng)關(guān)注好吧啦網(wǎng)其它相關(guān)文章!

標(biāo)簽: Java
相關(guān)文章:
主站蜘蛛池模板: 亚洲视频久久久 | 国产成人在线网址 | 国产精品77 | 香蕉久久av | 亚洲色图日本 | 精品欧美乱码久久久久久 | 婷婷视频网 | 黄色小视频免费观看 | 国产精品2018 | 亚洲视频a | 亚洲色图导航 | 欧美一区二区在线视频 | 亚洲无线观看 | 四虎地址8848 | 久久在线免费视频 | 国产精品亚洲成在人线 | 中文字幕在线日韩 | 新呦u视频一区二区 | 亚洲精品一区二区三区蜜桃久 | 一二三四国产 | 日本欧美一区二区三区 | 成人精品福利视频 | 国产在线二区 | 激情综合五月 | 国产日韩在线播放 | 青青草原av | 亚洲天堂视频在线观看 | 69av在线视频 | 国产免费成人av | 日韩欧美亚洲视频 | 亚洲区精品 | 久草热在线视频 | 日本国产在线观看 | 亚洲日本视频在线观看 | 国产三级在线观看视频 | 麻豆91精品91久久久 | 免费成人激情视频 | 国产又粗又黄又爽 | 色多多污污 | 亚洲不卡在线播放 | 国产调教在线 |