Effective Java Item 3 note

Enforce the singleton property with a private constructor or an enum type

Arwii
mycodingjourney
6 min readMay 23, 2018

--

什麼是singleton,我自己的理解是在application的生命週期中,只存在這唯一的一份instance的class。
本書上有提到兩種initial singleton的方式
1. instance是public final field的

好處是可以很明確就知道這個class是個singleton,書上有提到,現在的JVM都有實現把static factory method inline化,所以在效能上的優勢已經不存在了.

2. instance是public with static factory的
(如果在android studio裡面,可以透過快捷鍵方式產生出來的singleton就是長底下這個樣子)

第一個好處就是如果在不改變API的情況下,我們可以自己掌握這個class不是singleton.第二個好處則為item 27.

但書上表示public field的方式(第一種)比較簡單.(雖然android studio的內建是static factory)

這兩種方式都會在這個class第一次初始化的時候產生出instance,且正常的情況下是不會產生出第二個的.那書上有提到如果有privilege的client可以透過reflection的方式從AccessibleObject.setAccessible去調用private constructor,如果要防止這種使用,可以在constructor的地方確認在已經存在一個instance的情況下要產生第二個instance就丟出exception
像是:

就可以阻止底下這段想要拿到該singleton的程式碼

不過我有點訝異在android上面setAccessible是可以用的,看起來不用其他權限

(題外話1,有看到一篇blog寫到https://blog.csdn.net/xiangwanpeng/article/details/53220158
這觀點也蠻有趣的

題外話2,從這篇stackoverflow https://stackoverflow.com/questions/13211369/protection-from-reflection-android 的回答應該可以得出我的一個疑問,為什麼android上面可以用setAccessible,這裡面的回答是跟系統的設計有關,一般的JVM通常是跑在一個系統的process上,你沒有辦法掌控別的process跑的是什麼,所以需要這樣的防護,但在android上面的設計,基本上你的process沒有辦法讀取到別的process的內容,所以這在根本上就阻擋掉這樣的讀取,並不用在程式裡面特別去做一些保護,那如果你的城市裡面開了這個洞,也就怪不了別人,自行負責XD,不過也不至於影響到別的process就是了
)

另一個議題就是要怎麼讓singleton可以被serializable呢?(item 77)
先初步看一下Item 77裡面有提到,當一個class 去implement Serializable就不會是singleton了,所以要利用readResolve的method去提供原本的物件,但這種寫法還是會被item 76裡面提到的mutablePeriod攻擊所破解,所以還是建議以第三種方式Enum來建立singleton class,細節看到item 77的時候會再做連結.

3. 是可以用Enum來建立singleton(從java 1.5開始才support),這個寫法跟第一種的public field的方式相近,但更簡潔,也提供serializable的功能,可以防止被多次實例化.
同樣的也可以解決前面提到的reflection的攻擊.( 會出現java.lang.NullPointerException: Attempt to invoke virtual method ‘void java.lang.reflect.Constructor.setAccessible(boolean)’ on a null object reference )

對了最後順道一提,千萬不要這樣建立singleton class,這不是thread safe!!!小心建立出來不是singleton(誤

順道一提2
在查item4的資料的時候,剛好看到一篇建議不要使用singleton的原因,看起來應該是基於OO的概念上,不推薦使用這種global性質的class,然後會很不好寫測試程式.
https://stackoverflow.com/questions/137975/what-is-so-bad-about-singletons

--

--

Arwii
mycodingjourney

Try not to become a man of success, but rather try to become a man of value — A. Einstein