JavaRush /Java Blog /Random-TW /方法簽名

方法簽名

在 Random-TW 群組發布
你好!您已經掌握了使用欄位和方法建立自己的類別。今天我們就詳細說說方法。當然,我們在講座中不只一次這樣做過,但我們主要討論的是一般性的觀點。今天,我們將逐字分析這些方法 - 我們將找出它們的組成部分、創建它們的選項以及如何管理所有這些:) 讓我們開始吧!方法簽名 - 1

方法簽名

所有描述方法的程式碼稱為方法宣告。方法簽名包括按特定順序排列的方法名稱和參數類型。廣告的整體外觀可以描述如下:
модификатор доступа, тип возвращаемого значения, Name метода(список параметров) {
    // тело метода
}
我們以類別的幾個方法的聲明為例Dog
public class Dog {

   String name;

   public Dog(String name) {
       this.name = name;
   }

   public static void main(String[] args) {
       Dog max = new Dog("Max");
       max.woof();

   }

   public void woof() {
       System.out.println("Собака по имени " + name + " говорит \"Гав-гав!\"");
   }

   public void run(int meters) {
       System.out.println("Собака по имени " + name + " пробежала " + meters + " метров!");
   }

   public String getName() {
       return name;
   }
}

1. 存取修飾符

存取修飾符始終列在最前面。 所有類別方法Dog均由修飾符指定public。也就是說,我們可以從任何其他類別呼叫它們:
public class Main {

   public static void main(String[] args) {

       Dog butch = new Dog("Бутч");
       butch.run(100);
   }

}
正如您所看到的,類別方法Dog可以在類別中輕鬆存取Main。這要歸功於修飾符public。Java 中還有其他修飾符,但並非所有修飾符都允許您在另一個類別中使用方法。我們將在其他講座中討論它們。最重要的是記住修飾符的作用:其他類別中該方法的可用性/不可訪問性:)

2.static關鍵字

其中一種方法Dog,即main()由關鍵字指示static。如果存在,則必須在存取修飾符之後指定。還記得在之前的講座中我們討論過靜態類別變數嗎?當應用於方法時,這個詞具有大致相同的含義。如果一個方法被指定為static,這表示它可以在不引用特定類別物件的情況下使用。事實上,要main()在類別中運行靜態方法,Dog您不需要建立實例Dog;它無需建立實例即可運行。如果這個方法不是靜態的,那麼要使用它,我們需要先建立一個物件。

3.返回值。

如果我們的方法必須傳回某些內容,那麼我們將指示傳回值的類型。這可以在 getter 的範例中看到getName()
public String getName() {
   return name;
}
它傳回一個類型的物件String。如果方法不傳回任何內容,則指定關鍵字而非 type void,如方法中所示woof()
public void woof() {
   System.out.println("Собака по имени " + name + " говорит \"Гав-гав!\"");
}

同名方法

在某些情況下,我們的程式需要多個選項來決定方法的工作方式。我們為什麼不創造自己的人工智慧呢?Amazon 有Alexa,Yandex 有Alice,那為什麼我們會更差呢?:) 在有關鋼鐵人的電影中,托尼·斯塔克創造了自己傑出的人工智能- JARVIS 讓我們向這個精彩的角色致敬,並以他的名字命名我們的人工智慧:)我們必須教導賈維斯的第一件事是——向進入房間的人打招呼(如果如此偉大的智慧最終被證明是不禮貌的,那就太奇怪了)。
public class Jarvis {

   public void sayHi(String name) {
       System.out.println("Good evening, " + name + ", How are you doing?");
   }

   public static void main(String[] args) {
       Jarvis jarvis = new Jarvis();
       jarvis.sayHi("Tony Stark");
   }
}
控制台輸出:

Добрый вечер, Тони Старк, How ваши дела?
偉大的!賈維斯知道如何迎接進來的人。當然,最常見的是他的主人——東尼史塔克。但他可能不會一個人來!我們的方法sayHi()只接受一個參數作為輸入。因此,他只能向其中一位來者打招呼,而忽略另一位。不太禮貌,同意嗎?:/ 在這種情況下,為了解決問題,我們可以簡單地在類別中編寫兩個同名但參數不同的方法:
public class Jarvis {

   public void sayHi(String firstGuest) {
       System.out.println("Good evening, " + firstGuest + ", How are you doing?");
   }

   public void sayHi(String firstGuest, String secondGuest) {
       System.out.println("Good evening, " + firstGuest + ", " + secondGuest + ", How are you doing?");
   }

}
這稱為方法重載。重載使我們的計劃更加靈活並適應不同的工作選擇。讓我們檢查一下它是如何工作的:
public class Jarvis {

   public void sayHi(String firstGuest) {
       System.out.println("Good evening, " + firstGuest + ", How are you doing?");
   }

   public void sayHi(String firstGuest, String secondGuest) {
       System.out.println("Good evening, " + firstGuest + ", " + secondGuest + ", How are you doing?");
   }

   public static void main(String[] args) {
       Jarvis jarvis = new Jarvis();
       jarvis.sayHi("Tony Stark");
       jarvis.sayHi("Tony Stark", "Captain America");
   }
}
控制台輸出:

Добрый вечер, Тони Старк, How ваши дела? 
Добрый вечер, Тони Старк, Капитан Америка, How ваши дела?
太棒了,兩個選擇都有效:)但是,我們沒有解決問題!如果有三個客人怎麼辦?當然,我們可以再次重載該方法sayHi()以接受三位客人的名字。但也可以有 4 或 5 個,以此類推,無止境。是否有另一種方法可以教 Jarvis 使用任意數量的名稱,而不需要一百萬個方法重載sayHi()?:/ 當然有!否則,Java 會成為世界上最受歡迎的程式語言嗎?;)
public class Jarvis {

   public void sayHi(String...names) {

       for (String name: names) {
           System.out.println("Good evening, " + name + ", How are you doing?");
       }
   }

   public static void main(String[] args) {
       Jarvis jarvis = new Jarvis();
       jarvis.sayHi("Tony Stark");
       System.out.println();
       jarvis.sayHi("Tony Stark", "Captain America");
   }
}
作為參數傳遞的記錄 ( String...names) 允許我們指示將一定數量的字串傳遞給該方法。我們沒有提前指定應該有多少個,因此我們方法的操作現在變得更加靈活:
public class Jarvis {

   public void sayHi(String...names) {

       for (String name: names) {
           System.out.println("Good evening, " + name + ", How are you doing?");
       }
   }

   public static void main(String[] args) {
       Jarvis jarvis = new Jarvis();
       jarvis.sayHi("Tony Stark", "Captain America", "Black Widow", "Hulk");
   }
}
控制台輸出:

Добрый вечер, Тони Старк, How ваши дела? 
Добрый вечер, Капитан Америка, How ваши дела? 
Добрый вечер, Черная Вдова, How ваши дела? 
Добрый вечер, Халк, How ваши дела?
在這個方法內部,我們循環遍歷所有參數並將帶有名稱的現成短語輸出到控制台。這裡我們使用一個簡化的循環for-each(你已經遇到過)。這很棒,因為寫入String...names實際上意味著編譯器將所有傳遞的參數放入陣列中。因此, names您可以像使用數組一樣使用變量,包括循環訪問它。此外,它適用於任意數量的傳輸線路!兩個、十個、甚至一千個——該方法對於任意數量的客人都可以可靠地工作。比對所有可能的選項進行重載要方便得多,您同意嗎?:)讓我們再舉一個方法重載的例子。讓我們為 Jarvis 新增一個方法printInfoFromDatabase()。它將把有關該人的信息從資料庫列印到控制台。如果資料庫顯示一個人是超級英雄或超級惡棍,該資訊也會顯示在螢幕上:
public class Jarvis {

   public  void printInfoFromDatabase (String bio) {

       System.out.println(bio);
   }

   public void printInfoFromDatabase(String bio, boolean isEvil, String nickname) {

       System.out.println(bio);
       if (!isEvil) {
           System.out.println("Также известен How супергерой " + nickname);
       } else {
           System.out.println("Также известен How суперзлодей " + nickname);
       }
   }

   public static void main(String[] args) {
       Jarvis jarvis = new Jarvis();
       jarvis.printInfoFromDatabase("Лора Палмер. Дата рождения - 22 июля 1972, город Твин Пикс, штат Washington");
       System.out.println();
       jarvis.printInfoFromDatabase("Макс Эйзенхарт. Рост 188см, вес 86 кг.", true, "Магнето");
   }
}
結論:

Лора Палмер. Дата рождения - 22 июля 1972, город Твин Пикс, штат Washington
Макс Эйзенхарт. Рост 188см, вес 86 кг 
Также известен How суперзлодей Магнето
這就是我們的方法的工作原理,這取決於我們傳遞給它的資料。 另一個重要的一點:參數的順序很重要!假設我們的方法接受一個字串和一個數字作為輸入:
public class Man {

   public static void sayYourAge(String greeting, int age) {
       System.out.println(greeting + " " + age);
   }

   public static void main(String[] args) {

       sayYourAge("My age - ", 33);
       sayYourAge(33, "My age - "); //error!
   }
}
如果sayYourAge()類別方法Man接受字串和數字作為輸入,那麼這就是它們在程式中傳遞的順序!如果我們以不同的順序傳遞它們,編譯器將拋出錯誤,並且該人將無法說出他的年齡。順便說一句,我們在上一講介紹的構造函數也是方法!它們還可以重載(使用不同的參數集來建立多個建構函數),對於它們來說,傳遞參數的順序也非常重要。真正的方法!:)

如何呼叫具有相似參數的方法

大家知道,Java中有一個字null。使用它時,了解 null 既不是物件也不是資料類型非常重要。introduce()假設我們有一個 Man 類別和一個聲明人的姓名和年齡的方法。在這種情況下,年齡可以以文字的形式傳達,也可以以數字的形式表達。
public class Man {

   public void introduce(String name, String age) {
       System.out.println("Меня зовут " + name + ", мой возраст - " + age);
   }

   public void introduce(String name, Integer age) {
       System.out.println("Меня зовут " + name + ", мой возраст - " + age);
   }

   public static void main(String[] args) {

       Man sasha = new Man();
       sasha.introduce("Sasha", "двадцать один");

       Man masha = new Man();
       masha.introduce("Мария", 32);
   }
}
我們已經熟悉重載,因此我們知道該方法兩次都會按預期工作:

Меня зовут Саша, мой возраст - двадцать один 
Меня зовут Мария, мой возраст - 32 
但是如果我們傳遞 null 作為第二個參數,而不是字串或數字,會發生什麼事?
public static void main(String[] args) {

   Man victor = new Man();
   victor.introduce("Виктор", null);//Ambiguous method call!
}
我們會得到一個編譯錯誤!「Ambigously method call」錯誤被翻譯為「ambiguously method call」。為什麼會出現這種情況,什麼是「歧義」?其實很簡單。問題是,我們有該方法的兩種變體:withString和 withInteger作為第二個參數。但String, 和Integer都可以為空!對於這兩種類型(因為它們是引用類型),null 是預設值。這就是為什麼在這種情況下編譯器無法確定應該呼叫哪個版本的方法。解決這個問題非常簡單。重點是 null 可以明確轉換為特定的參考類型。因此,在呼叫方法時,可以在括號中指明第二個參數所需的資料類型!編譯器會理解你的「提示」並呼叫所需的方法:
public class Man {

   public void introduce(String name, String age) {
       System.out.println("Метод с двумя строками!");
       System.out.println("Меня зовут " + name + ", мой возраст - " + age);
   }

   public void introduce(String name, Integer age) {
       System.out.println("Метод со строкой и числом!");
       System.out.println("Меня зовут " + name + ", мой возраст - " + age);
   }

   public static void main(String[] args) {

       Man victor = new Man();
       victor.introduce("Виктор", (String) null);
   }
}
結論:

Метод с двумя строками! 
Меня зовут Виктор, мой возраст - null
但如果數字參數是基元int,而不是引用類型的對象Integer,則不會發生此類錯誤。
public class Man {

   public void introduce(String name, String age) {
       System.out.println("Метод с двумя строками!");
       System.out.println("Меня зовут " + name + ", мой возраст - " + age);
   }

   public void introduce(String name, int age) {
       System.out.println("Метод со строкой и числом!!");
       System.out.println("Меня зовут " + name + ", мой возраст - " + age);
   }

   public static void main(String[] args) {

       Man victor = new Man();
       victor.introduce("Виктор", null);
   }
}
你猜到原因了嗎?如果你猜對了,幹得好:)因為基元不能等於 null。現在,編譯器只有一種調用該方法的選項introduce()- 使用兩行。每次呼叫該方法時都會處理此版本的方法。
留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION