你好!在前面的章節中,您已經學習瞭如何使用方法和字段聲明您自己的完整類。在今天的課程中,我們將討論 Java 中的 Getters 和 Setters。這是一個重大的進步,幹得好!但現在我不得不告訴你一個不愉快的事實。我們沒有正確聲明我們的類!為什麼?乍一看,下面的類沒有任何錯誤:
這些名稱來自“get”(即“獲取字段值的方法”)和“set”(即“設置字段值的方法”)。讓我們看看它們在我們的 Cat 類中的樣子:
相反,製造商為您提供了一個界面:用戶只需輸入正確的數字,按下綠色的通話按鈕,通話就會開始。她不關心電路和電線內部發生了什麼,或者它們是如何完成工作的。在這個例子中,公司限制了對手機“內部”(數據)的訪問,並且隻公開了一個接口(方法)。結果,用戶得到了她想要的東西(打電話的能力),當然不會破壞裡面的任何東西。 為了鞏固您所學的知識,我們建議您觀看我們的 Java 課程中的視頻課程
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!");
}
}
但確實如此。想像一下,您正在工作並編寫這個Cat類來表示貓。然後你回家。你不在的時候,另一個程序員來上班了。他創建了自己的Main類,並開始使用您編寫的Cat類。
public class Main {
public static void main(String[] args) {
Cat cat = new Cat();
cat.name = "";
cat.age = -1000;
cat.weight = 0;
}
}
他為什麼這樣做以及它是如何發生的(也許這個人累了或者睡眠不足)並不重要。其他事情很重要:我們當前的Cat類允許為字段分配絕對瘋狂的值。結果,該程序的對象具有無效狀態(例如這只 -1000 歲的貓)。那麼我們在聲明我們的類時犯了什麼錯誤呢?我們公開了班級的數據。姓名、年齡和體重字段是公開的。它們可以在程序的任何地方訪問:只需創建一個Cat對象,任何程序員都可以通過點 ( . ) 運算 符直接訪問其數據
Cat cat = new Cat();
cat.name = "";
這裡我們直接訪問名稱字段並設置它的值。我們需要以某種方式保護我們的數據免受不當的外部干擾。我們需要做什麼?首先,所有實例變量(字段)都必須標有私有修飾符。Private 是 Java 中最嚴格的訪問修飾符。一旦這樣做, Cat類的字段將無法在類外訪問。
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 class Main {
public static void main(String[] args) {
Cat cat = new Cat();
cat.name = "";//error! The Cat class's name field is private!
}
}
編譯器看到這一點並立即生成錯誤。現在這些字段有點受到保護。但事實證明,我們可能過於嚴格地關閉了訪問權限:即使需要,您也無法在程序中獲取現有貓的體重。這也不是一種選擇。實際上,我們的類基本上是不可用的。理想情況下,我們需要允許某種有限的訪問:
- 其他程序員應該能夠創建Cat對象
- 他們應該能夠從現有對像中讀取數據(例如,獲取現有貓的名稱或年齡)
- 還應該可以分配字段值。但在這樣做時,應該只允許有效值。我們的對象應該避免無效值(例如 age = -1000 等)。

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) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int getWeight() {
return weight;
}
public void setWeight(int weight) {
this.weight = weight;
}
}
如您所見,它們看起來非常簡單 :) 它們的名稱通常由“get”/“set”加上相關字段的名稱組成。例如,getWeight()方法返回調用它的對象的權重字段的值。這是它在程序中的樣子:
public class Main {
public static void main(String[] args) {
Cat smudge = new Cat("Smudge", 5, 4);
String smudgeName = smudge.getName();
int smudgeAge = smudge.getAge();
int smudgeWeight = smudge.getWeight();
System.out.println("Cat's name: " + smudgeName);
System.out.println("Cat's age: " + smudgeAge);
System.out.println("Cat's weight: " + smudgeWeight);
}
}
控制台輸出:
Cat's name: Smudge
Cat's age: 5
Cat's weight: 4
現在另一個類 ( Main ) 可以訪問Cat字段,但只能通過 getter。請注意,getter 具有 public 訪問修飾符,即它們可以從程序中的任何地方使用。但是如何分配值呢?這就是 setter 方法的用途
public void setName(String name) {
this.name = name;
}
如您所見,它們也很簡單。我們在Cat對像上調用setName()方法,傳遞一個字符串作為參數,並將該字符串分配給對象的名稱字段。
public class Main {
public static void main(String[] args) {
Cat smudge = new Cat("Smudge", 5, 4);
System.out.println("Cat's original name: " + smudge.getName());
smudge.setName("Mr. Smudge");
System.out.println("Cat's new name: " + smudge.getName());
}
}
在這裡,我們同時使用了 getter 和 setter。首先,我們使用一個 getter 來獲取並顯示貓的原始名稱。然後,我們使用 setter 分配一個新名稱(“Mr. Smudge”)。然後我們再次使用 getter 來獲取名稱(以檢查它是否真的改變了)。控制台輸出:
Cat's original name: Smudge
Cat's new name: Mr. Smudge
那麼有什麼區別呢?即使我們有設置器,我們仍然可以為字段分配無效值:
public class Main {
public static void main(String[] args) {
Cat smudge = new Cat("Smudge", 5, 4);
smudge.setAge(-1000);
System.out.println("Smudge's age: " + smudge.getAge());
}
}
控制台輸出:
Smudge's age: -1000 years
不同之處在於 setter 是一種成熟的方法。與字段不同,方法允許您編寫必要的驗證邏輯以防止出現不可接受的值。例如,您可以輕鬆地防止將負數指定為年齡:
public void setAge(int age) {
if (age >= 0) {
this.age = age;
} else {
System.out.println("Error! Age can't be negative!");
}
}
現在我們的代碼可以正常工作了!
public class Main {
public static void main(String[] args) {
Cat smudge = new Cat("Smudge", 5, 4);
smudge.setAge(-1000);
System.out.println("Smudge's age: " + smudge.getAge());
}
}
控制台輸出:
Error! Age can't be negative!
Smudge's age: 5 years
在 setter 內部,我們創建了一個限制,以防止我們嘗試設置無效數據。Smudge 的年齡沒有改變。您應該始終創建 getter 和 setter。即使對您的字段可以採用的值沒有限制,這些輔助方法也不會造成任何傷害。想像一下以下情況:您和您的同事正在一起編寫程序。您創建一個帶有公共字段的Cat類。所有的程序員都在隨心所欲地使用它們。然後在一個晴朗的日子你意識到:“糟糕,遲早有人可能會不小心給權重分配一個負數!我們需要創建 setter 並將所有字段設為私有!” 你就是這麼做的,並立即破解了你同事編寫的所有代碼。畢竟,他們貓領域直接。
cat.name = "Behemoth";
現在字段是私有的,編譯器會拋出一堆錯誤!
cat.name = "Behemoth";//error! The Cat class's name field is private!
在這種情況下,最好隱藏字段並從一開始就創建 getter 和 setter。您所有的同事都會使用它們。如果你後來才意識到你需要以某種方式限製字段值,你可以在 setter 中編寫檢查。沒有人的代碼會被破壞。當然,如果你想訪問一個字段只是“只讀”,你可以只為它創建一個 getter。只有方法應該在外部可用(即在您的班級之外)。數據應該被隱藏。我們可以拿手機做個類比。想像一下,你拿到的不是通常的封閉式手機,而是一個外殼打開的手機,裡面有各種突出的電線、電路等。但手機能正常工作:如果你真的很努力地戳電路,你甚至可能能夠打電話。但是你'

GO TO FULL VERSION