CodeGym /Java Blog /Toto sisi /Java 中的訪問修飾符
John Squirrels
等級 41
San Francisco

Java 中的訪問修飾符

在 Toto sisi 群組發布
你好!在今天的課程中,我們將熟悉訪問修飾符的概念,並考慮如何使用它們的示例。當然,說“熟悉”並不完全正確:您已經從之前的課程中熟悉其中的大部分內容。為了以防萬一,讓我們回顧一下最重要的一點。修飾符訪問通常是關鍵字,用於調節對代碼不同部分的訪問。為什麼是“最經常”?因為其中之一是默認設置的,沒有使用關鍵字 :) Java 有四種訪問修飾符。我們按照從最嚴格到最“寬鬆”的順序列出它們:
  • 私人的;
  • 默認(包可見);
  • 受保護;
  • 民眾。
讓我們看一下它們中的每一個,並確定它們何時可能有用。我們將舉例說明 :)

私有修飾符

訪問修飾符。 私有、受保護、默認、公共 - 2private是最嚴格的訪問修飾符。它將數據和方法的可見性限制在單個類中。您從關於 getter 和 setter 的課程中知道了這個修飾符。還記得這個例子嗎?

public class Cat {

   public String name;
   public int age;
   public int weight;

   public Cat(String name, int age, int weight) {
       this.name = name;
       this.age = age;
       this.weight = weight;
   }

   public Cat() {
   }

   public void sayMeow() {
       System.out.println("Meow!");
   }
}

public class Main {

   public static void main(String[] args) {

       Cat cat = new Cat();
       cat.name = "";
       cat.age = -1000;
       cat.weight = 0;
   }
}
我們在上一課中考慮過它。我們在這裡犯了一個嚴重的錯誤:我們公開了我們的數據,這使得其他程序員可以直接訪問這些字段並更改它們的值。更重要的是......這些值是在沒有任何檢查的情況下分配的。這意味著我們的程序可以創建一隻名為“”的貓,年齡為-1000 歲,體重為 0。為了解決這個問題,我們使用了 getter 和 setter,還使用了 private 修飾符來限制對數據的訪問。

public class Cat {

   private String name;
   private int age;
   private int weight;

   public Cat(String name, int age, int weight) {
       this.name = name;
       this.age = age;
       this.weight = weight;
   }

   public Cat() {
   }

   public void sayMeow() {
       System.out.println("Meow!");
   }

   public String getName() {
       return name;
   }

   public void setName(String name) {
       // input parameter check
       this.name = name;
   }

   public int getAge() {
       return age;
   }

   public void setAge(int age) {
       // input parameter check
       this.age = age;
   }

   public int getWeight() {
       return weight;
   }

   public void setWeight(int weight) {
       // input parameter check
       this.weight = weight;
   }
}
基本上,限制對字段的訪問和實現 getter 和 setter 是最常見的私有化示例會用到實際工作中。也就是說,這個修飾符的主要目的是在程序中實現封裝。順便說一句,這不僅適用於字段。想像一下,在您的程序中有一個方法可以實現一些非常複雜的功能。我們可以舉個例子嗎?假設您的 readDataFromCollider() 方法接受數據地址作為輸入,以字節格式從大型強子對撞機讀取數據,將此數據轉換為文本,將其寫入文件並打印。連方法的描述看起來都嚇人,更不用說代碼了:) 為了使代碼更具可讀性,最好不要將所有方法的複雜邏輯都寫在一個地方。相反,我們應該將功能分解為單獨的方法。例如,readByteData()方法負責讀取數據,convertBytesToSymbols()方法將從collider讀取的數據轉換為文本,saveToFile()方法將接收到的文本保存到文件中,printColliderData ()方法打印我們的數據文件。最後,我們的readDataFromCollider()方法會簡單得多:

public class ColliderUtil {

   public void readDataFromCollider(Path pathToData) {
       byte[] colliderData = readByteData(pathToData);
       String[] textData = convertBytesToSymbols(colliderData);
       File fileWithData = saveToFile(textData);
       printColliderData(fileWithData);
   }

   public byte[] readByteData(Path pathToData) {

       // Reads data in bytes
   }

   public String[] convertBytesToSymbols(byte[] colliderDataInBytes) {

       // Converts bytes to characters
   }

   public File saveToFile(String[] colliderData) {

       // Saves read data to a file
   }

   public void printColliderData(File fileWithColliderData) {

       // Prints data from the file
   }
}
但是,正如您從有關接口的課程中所記得的那樣,用戶只能訪問外部接口。而我們的4個方法不在其中。它們是輔助方法:我們創建它們是為了提高代碼的可讀性,而不是將四個不同的任務塞進一個方法中。您不需要授予用戶訪問這些方法的權限。如果用戶在使用碰撞器時可以訪問convertBytesToSymbols()方法,他們很可能只是對該方法感到困惑,並想知道它的用途。轉換了哪些字節?哪兒來的呢?為什麼要將它們轉換為文本?在此方法中執行的邏輯不是向用戶公開的界面的一部分。只有readDataFromCollider()方法是接口的一部分。那麼我們如何處理這四種“內部”方法呢?正確的!使用private修飾符來限制對它們的訪問。這樣做允許他們在類中和平地執行他們的工作,而不會混淆用戶,用戶不需要知道每個單獨方法的邏輯。

public class ColliderUtil {

   public void readDataFromCollider(Path pathToData) {
       byte[] colliderData = readByteData(pathToData);
       String[] textData = convertBytesToSymbols(colliderData);
       File fileWithData = saveToFile(textData);
       printColliderData(fileWithData);
   }

   private byte[] readByteData(Path pathToData) {
       // Reads data in bytes
   }

   private String[] convertBytesToSymbols(byte[] colliderDataInBytes) {
       // Converts bytes to characters
   }

   private File saveToFile(String[] colliderData) {
       // Saves read data to a file
   }

   private void printColliderData(File fileWithColliderData) {
       // Prints data from the file
   }
}

受保護修飾符

下一個最嚴格的修飾符是protected受保護訪問修飾符。 私有、受保護、默認、公共 - 3訪問修飾符標記的字段和方法將可見:
  • 在與我們相同的包中包含的所有類中;
  • 在繼承我們類的所有類中。
起初,很難想像什麼時候可能需要這樣做。不要感到驚訝:protected的用例遠少於private 的用例,而且它們非常具體。想像一下,我們有一個AbstractSecretAgent抽像類,它表示某個情報服務中的秘密代理人,以及一個包含此類及其後代的top_secret包。FBISecretAgentMI6SecretAgentMossadSecretAgent等具體類都繼承了它。在抽像類內部,我們要實現一個代理計數器。當在程序某處創建新代理時,它會增加。包絕密;

public abstract class AbstractSecretAgent {

   public static int agentCount = 0;
}
但我們的特工是保密的!這意味著他們而不是其他人應該知道其中有多少存在。我們可以輕鬆地將protected修飾符添加到agent_counter字段。然後其他秘密特工類和位於我們的top_secret包中的其他類的實例可以獲取它的值。

public abstract class AbstractSecretAgent {

   protected static int agent_counter = 0;
}
這就是需要protected修飾符 的專門任務:)

包可見修飾符

列表中的下一個是默認修飾符,也稱為包可見修飾符。它不是由關鍵字指示的,因為 Java 默認將它應用於所有字段和方法。如果您在代碼中編寫以下內容:

int x = 10
x變量將具有此可見訪問權限。很容易記住它的作用。基本上,default = protected inheritance :) 和protected修飾符一樣,它的應用是有限的。大多數情況下,默認訪問用於包含一些實用程序類的包中,這些實用程序類未實現包中所有其他類的功能。讓我們舉個例子。想像一下,我們有一個“服務”包。它包含各種與數據庫一起工作的類。比如有一個從數據庫中讀取用戶數據的UserService類,一個CarService從同一數據庫和其他類讀取汽車數據的類,每個類都使用特定類型的對象並從數據庫中讀取相應的數據。

package services;

public class UserService {
}

package services;

public class CarService {
}
但是數據庫中的數據很容易是一種格式,而我們需要另一種格式。假設用戶的生日在數據庫中存儲為 <TIMESTAMP WITH TIME ZONE>...

2014-04-04 20:32:59.390583+02
...相反,我們需要最簡單的對象 — java.util.Date。為了解決這個問題,在services包裡面,我們可以創建一個特殊的Mapper類。它將負責將數據從數據庫轉換為我們熟悉的 Java 對象。一個簡單的幫助類。我們通常將所有類都聲明為public class ClassName,但這不是必需的。我們可以將我們的助手類簡單地聲明為class Mapper在這種情況下,它仍然可以正常工作,但服務包之外的任何人都看不到它!

package services;

class Mapper {
}


package services;

public class CarService {

   Mapper mapper;
}
這是基本的推理:為什麼包外的任何人都需要看到一個僅適用於該包中的類的助手類?

公共修飾符

最後但同樣重要的是,公共修飾符!您在學習 CodeGym 的第一天第一次運行public static void main(String[] args)時遇到了這個修飾符。 訪問修飾符。 私有、受保護、默認、公共 - 4現在您已經學習了有關接口的課程,其目的對您來說是顯而易見的 :) 畢竟,創建public修飾符是為了向用戶提供一些東西。例如,您的程序的界面。假設您編寫了一個可以將俄語文本翻譯成英語的翻譯程序。您創建了一個實現所有必要邏輯的translate(String textInRussian)方法。您用public這個詞標記了這個方法,現在它是接口的一部分:

public class Translator {

   public String translate(String textInRussian) {

       // Translates text from Russian to English
   }
}
您可以將此方法綁定到屏幕上的“翻譯”按鈕,您就完成了!任何人都可以使用它。標有public修飾符的代碼部分供最終用戶使用。舉一個真實的例子,private是針對電視內部發生的所有進程,而public是針對遙控器上用於管理電視的按鈕。更重要的是,用戶不需要知道電視是如何製造的或它是如何工作的。遙控器是一組公共方法:on()off()nextChannel()previousChannel()increaseVolume()decreaseVolume()等。 為了鞏固您所學的知識,我們建議您觀看我們的 Java 課程中的視頻課程
留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION