天天看點

Java 通路權限控制:public、private、protected

本篇文章主要介紹 Java 的通路權限控制。先問大家一個問題:人在什麼面前最容易失去抵抗力?

美色,算是一個,比如說西施的貢獻薄就是忍辱負重、以身報國、助越滅吳;金錢,算是另外一個,我們古人常說“錢乃身外之物,生不帶來死不帶去”,但我們又都知道“有錢能使鬼推磨”。

除去美色和金錢,我認為還有一個,就是讀者的認可——“二哥,你的文章真的很棒,我特别喜歡。希望能多多更新 Java 基礎知識,真的是受益良多,就好像是在讀王小波的散文,但又學了程式設計!”——你說,收到讀者這樣暖暖的評語,還需要美色和金錢?“兩者皆可抛”嘛。

01、public 的慘案

舒淇曾說過這樣一句令人感到震撼後又虎軀一震的話:“我要把我曾經脫下的衣服一件一件的穿回來!”如今,她做到了——通過自己的努力,不僅得到了觀衆的認可,得了很多大獎,還收獲了幸福。盡管,真的是盡管,還有一些“憶往昔峥嵘歲月稠”的朋友在電腦硬碟的深處留存了一些舒淇早年的珍藏版照片(「沉默王二」公衆号背景回複“1024”有你想不到的驚喜)。

我扯這個例子主要為了證明一句話——通路控制(或隐藏具體實作)與“最初的實作并不恰當”有關——如果舒淇當初那些照片的權限不是那麼公開化的話,那現在就可以私自燒毀了;或者換一種出道方式;然而沒有如果了。

在你最初的程式設計生涯中,不知道你是否創作過下面這樣“優秀”的代碼,就像程式清單1-1那樣。

程式清單1-1:

public class NiubiUtil {
    public static Date getNextDay() {
  long millis = 24 * 60 * 60 * 1000;
  try {
    Thread.sleep(millis);
  } catch (InterruptedException e) {
    e.printStackTrace();
  }
  return new Date(System.currentTimeMillis());
    }
}      

本來你這些代碼隻是自己寫着玩呢,誰知道被一個叫小二哥的同僚不經考量地調用了。這一調用不要緊,小二哥的代碼真的活活地等了一整天——産品經理小王老師某一天心血來潮非要測試小二哥的代碼,然後點了檢視下一天的按鈕,程式真的在那靜靜地等着,直到下一天真的來臨。

後果是,小王老師為了安撫使用者們躁動的情緒把小二哥直接拉出去祭天了;你躲在角落裡瑟瑟發抖,心裡默默念叨了句話——“小二哥,你走好,兄弟真的對不住了”。

一場血淋漓的慘案啊!隻因為 Java 通路權限控制的使用不當——該 private 的方法,結果失誤寫成了 public——論通路權限控制的重要性。

02、 private 更易重構

我已經在 Java 程式設計的道路上混迹了多年,自然也寫過無數曾經看起來那麼“優秀”的代碼。随着時間的推移,再回首過往的那些代碼時,總有一種“這真的出自我手?”的疑問。

這種疑問包含兩層意思,一層是感慨真的寫得好,就好像年老時的李白看見自己年少時寫的《望廬山瀑布》:“日照香爐生紫煙,遙看瀑布挂前川;疑是銀河落九天,飛流直下三千尺。”——喲,老子年輕時寫得也不賴啊。

另外一層是感慨真的寫得差,比如說程式清單1-1,往事不堪回首啊,隻能都随風,都随風,都随風而去!

對于這些寫得很差的代碼,我每次看見都想再修改一次,期待她更可讀、更易了解、更具可維護性;但在美好的願景下,也存在着巨大的壓力,因為有好多其他的地方引用了要修改的代碼,牽一發而動全身啊。

在變與不變的過程中,我發現——通路權限控制真的太重要了。在寫代碼的過程中,我們需要盡量遵循這樣一個原則——除了那些必須 public 的方法,盡量把其他方法定義為 private。這樣做的好處是,在重構 private 方法的時候不必再擔驚受怕,因為它們不會被類外部通路到。

03、 protected 保護财産

我們知道,public 權限修飾符使類的一切方法和屬性對外可見;private 權限修飾符使類的一切方法和屬性隻對内部可見;那麼 protected 權限修飾符呢?

假如有一個叫王二的家夥,他有三個屬性,分别是私生活、外在形象和被保護的财産,就像程式清單3-1那樣。

程式清單3-1:

public class Wanger {
    // 私生活
    private String life;
    // 外在形象
    public String image;
    // 被保護的财産
    protected String money;
}      

王二生了一個孩子叫王小二,就像程式清單3-2那樣。

程式清單3-2:

public class Wangxiaoer extends Wanger{

@Override

public String toString() {

 return "可以繼承的财産:" + money + ";塑造的人設:" + image + ";得不到的私生活:";

}

}

王小二可以繼承到王二的财産 money(據說王二在王小二出生的第一個月為其存了 100,以後每個月的利率為 12%,現在存款是 3758.17,你知道王小二現在多大了嗎?),也可以模仿一點父親的外在形象 image,但卻不能按照父親的私生活方式生活。

注意到三個權限修飾符的差別了嗎?

protected 可以保護王二的财産順利地繼承到王小二那裡,外界的人是通路不到的;public 不安全,因為不僅王小二可以繼承通路,外界其他人也可以通路;private 太私有化,不僅外界通路不到,王小二也繼承不到。

04、 總結

通路權限控制的兩個重要作用:第一是為了防止外界觸碰到不該觸碰的地方(private 修飾的成員變量或者方法);第二是讓類的設計者可以更改内部(private 修飾的成員變量或者方法)的工作方式,而不必擔心有沒有對外界造成幹擾。