2010-02-17 40 views
50

什麼是更好的做法以及爲什麼:通過私有字段上的受保護字段或公共獲取者訪問基類變量。Java受保護字段vs公共獲取者

(該吸氣劑將公開,不管)

+1

[基類中的受保護字段很糟糕](http://stackoverflow.com/questions/3182653/are-protected-members-fields-really-that-bad)。 – RBT 2017-02-04 00:29:33

回答

53

如果有將是一個公共的getter反正,你爲什麼要將領域本身暴露得比絕對必要的更廣泛?這意味着它可以立即通過子類進行寫入(除非最終開始)。

我個人喜歡我所有的領域都是私有的:它提供了一個更清晰的API和實現之間的分離。我認爲超類和子類之間的關係類似於調用者和被調用者之間的關係 - 對底層實現的更改不應該破壞子類,而應該超過他們應該打破調用者。字段的名稱是不應該影響其他類的實現細節。

誠然我的觀點是偶爾看到的有點極端的......

+0

在我公認的有限的經驗中,我沒有找到使用受保護字段的好理由,而且似乎總是會導致其他問題。我同意在幾乎所有情況下最好讓它們保密。 – Feanor 2010-02-17 10:10:11

+0

@ Jon.Could你提供一個工作的例子/插圖爲這種情況下超類中的變量/方法在子類中使用。如果你可以回覆 – Deepak 2011-03-19 13:01:12

+7

@Deepak:我很害怕我沒有有時間給我提供的每個Java答案的完整示例。你爲什麼不自己嘗試一下,如果遇到問題,問一個問題? – 2011-03-19 16:32:54

8

直接字段訪問不是優選的。使用publicprotected制定者和獲得者。

吸氣不必public - 如果你婉隱藏「外人」的數據,但給的數據子類中,protected

14

你應該總是針對一類的公共API的程序,即使用公共方法。

原因很簡單。將來的某一天,您或其他人可能想要更改實施。這應該總是可能的。如果你依賴實例變量,你可以限制自己。

此外,訪問該變量時,您無法控制該變量是隻讀還是可以在此變量更改時添加檢查。

如果你使用setter/getters,你可以隨時添加驗證,稍後檢查等。您也可以只提供一個getter來使變量只讀。

+2

如果某人*暴露了一個變量,他們應該將它視爲不可改變的,就像他們應該使用公共/受保護的方法一樣。如果有人暴露了一個領域然後改變了領域,他們顯然並不在意打破其他開發者的位置,並且很可能會改變方法:( – 2010-02-17 10:22:59

+0

True。這就是爲什麼我添加了如此多的「應該」我的評論:) 但大多數情況下,更容易維護一個現有的公共方法,只是添加一個重載/特殊版本,這就是爲什麼我喜歡私有變量(公共靜態最終常量除外) – phisch 2010-02-17 10:41:22

3

Sun關於控制訪問字段的一些建議是here.請注意,使字段受保護也暴露給包,而不僅僅是子類。一般而言,正如上面的鏈接所述,除非有充分理由不這樣做,否則字段應該是私人的。

+1

+1提及保護'暗示*包私人*訪問級別 – ifloop 2014-10-24 08:04:56

0

從子類訪問受保護的字段是繼承違反封裝的一種方式。這個原因使用公共API更好。

3

有效的Java第二版說

項目13:儘量減少類和成員

無障礙經驗法則很簡單:使每類或成員爲不可訪問的 可能。換句話說,使用與您正在編寫的軟件的正常運行一致的最低可能訪問級別。

所以,如果你不確定爲什麼你需要一個受保護的類成員(即你不需要該字段可以被相同包中的子類或類訪問),那麼聲明它是私有的。如果你想從課堂外進行設置,那麼請製作一個公開製片員。但是,如果你的成員是最終成員,那麼在某些情況下使它成爲受保護的(即它不會顯示敏感信息)。

我想提到的一個潛在的安全問題是,如果你有一個聲明爲protected final(甚至是public final)的數組,數組引用是final的(不能被修改),但是數組中的對象不是最終的(入侵者可以改變陣列內容)。


如果你知道C++,你可能知道,

const int * someMember

不同於

int * const someMember

後者就像是Java中的最後一個數組。


對於上述安全漏洞的修復方法是返回數組的深層副本或返回它作爲一個只讀列表。

1

通常,您應該使用Sun的建議。有一個很大的例外:如果你正在爲Android編程。

原因是性能。對於每個虛擬方法調用,使用查找表將方法路由到其對象時都會涉及開銷。訪問本地變量時不涉及此開銷。

這裏有一些鏈接,在更深入一點解釋:

http://developer.android.com/training/articles/perf-tips.html#GettersSetters

http://blog.leocad.io/why-you-shouldnt-use-getters-and-setters-on-android/

重要的是要知道你要完成的任務:

  1. 的字段的值應該可以使用公共接口訪問客戶端代碼。
  2. 該字段旨在被子類使用。

在純粹的Java中,getters和setters完成了這兩項任務。但Android是不同的。如果你正在做#1,那麼你應該使用公共getters和setter。如果你在做#2,那麼你應該使用受保護的字段。如果你正在做這兩個,使用兩者。

相關問題