簡單來說,private並不是解決「安全」問題的。
安全是指不讓程式碼被非法看到/存取。但是只要人能拿到程式碼,總會有辦法去檢視和改變程式碼。其他答案提到反射可以用SecurityManager來防止private被存取。但是從更高一層的角度,即便使用了SecurityManager,還是可以透過各種方式拿到java的bytecode,並做任意修改。比如有asm這樣的lib,也有instrument api這種東西可以幫你。所以記得,如果你真有一段程式碼不允許被別人看/用,就不要把這段程式碼放到其他人可以碰到的地方,而是做一個server,透過介面允許有限制的存取。其他人想破解,只能破解你的伺服器閘道器和彈板機器。
關於真正的安全性,可以參考啟用伺服器的工作原理private想表達的不是「安全性」的意思,而是OOP的 封裝 概念,是一種編譯器可以幫助你的設計上的hint。這就像是一家沒人的店掛了個牌子「閑人免進」,但你真要進去還是有各種辦法可以辦到。所以private,以及所有其他的access modifier都有一層隱含的含義:如果你按照遵守這套規則,開發者可以保證不問題(不考慮bug的情況下);否則,後果自負。
比如,你在用spring的IoC的時候,你知道你要「註入」,不管它是不是private的,你知道「註入」是你自己控制的,是你設計好的效果。那麽透過spring的IoC利用反射幫你註入一些private property是再正常不過的用法。
再比如,單元測試,你就想測一個private方法。但是因為private的緣故就是測不了。於是你可以用反射繞開這個限制,開心的做測試。
雖說某些人堅持「不應該測試private方法,而應該透過測試其他方法間接測試private方法,但並沒有形成廣泛的共識。這裏不對這個問題展開。雖然能繞開,但繞開的程式碼很繁瑣。久而久之就會厭倦。畢竟, 程式碼應該為你工作,而不是你為程式碼工作 。因此,我的經驗是通常會用protected或者default來代替private。我曾設想runtime應該給一種執行模式,透過設定一個啟動參數使其不管private這類的限制,這樣做UT,做profiling等工作都會輕松許多。等到最後釋出時,再用普通模式。但可惜現實當中並沒有這種設定。
評論區提到了Android裏的VisibleForTesting,可以實作我期望的功能。大贊!感謝 @尤華傑我之所以敢用protected/default來代替private是因為現實當中非private不可的情景非常少見。實際上,很多時候private帶來的麻煩比起帶來的好處要多,這是因為很多時候對OOP的誤用造成的。OOP的誤用造成了無謂的private,然後逼著你必須得繞開private。
其實private就是個約定而已。看看其他語言,比如python,它的「private「是一種很松散的約定,所有private的成員都用底線開頭,告訴呼叫者「不要隨便呼叫我哦」,但是如果真呼叫了也就呼叫了。C++,透過指標就能繞開private。有人說,private會避免新手誤用。但問題是,大家從出道開始,自己或者周圍的同事朋友有誰曾經出過這個問題?IDE知道一個成員當前不能存取,就根本就不會提示。如果一個人已經開始透過原始碼/反編譯研究「我能不能呼叫這個私有方法了「,他還算是一個菜鳥嗎?他會不知道這裏的潛在風險嗎?如果真的誤用了,code review能過嗎?測試能過嗎?如果一個公司因為誤用private成員,造成了重大的損失,那這個公司就活該倒閉算了,不要在世上丟人。
OOP是一種編程思想,是眾多編程思想中的一種。 是開發者決定了一個問題應該用OOP合適,並且用了Java這樣的語言來簡化自己開發OOP程式碼時的工作。 如果抱著這種態度,就不會誤用,因為private在開發者的心中。其他人也不太可能誤用,如果他上過幾天java培訓。不要因為語言是OOP的就去套,把不適合的OOP的程式碼強用OOP的各種套路實作,然後給自己後續的維護擴充套件埋坑。