JavaRush /Blog Java /Random-VI /Chữ ký phương thức

Chữ ký phương thức

Xuất bản trong nhóm
Xin chào! Bạn đã thành thạo việc tạo các lớp của riêng mình với các trường và phương thức. Hôm nay chúng ta sẽ nói chi tiết về các phương pháp. Tất nhiên, chúng tôi đã làm điều này nhiều lần trong các bài giảng của mình, nhưng chúng tôi chủ yếu nói về những điểm chung. Hôm nay chúng ta sẽ phân tích theo nghĩa đen các phương pháp “theo từng phần” - chúng ta sẽ tìm hiểu xem chúng bao gồm những gì, những lựa chọn nào để tạo ra chúng tồn tại và cách quản lý tất cả những điều này :) Đi thôi!Chữ ký phương thức - 1

Chữ ký phương thức

Tất cả mã mô tả một phương thức được gọi là khai báo phương thức . Chữ ký phương thức bao gồm tên phương thức và loại tham số theo một thứ tự cụ thể. Diện mạo chung của quảng cáo có thể được mô tả như sau:
модификатор доступа, тип возвращаемого значения, Name метода(список параметров) {
    // тело метода
}
Hãy lấy một ví dụ về khai báo một số phương thức của lớp 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. Công cụ sửa đổi quyền truy cập

Công cụ sửa đổi truy cập luôn được liệt kê đầu tiên. Tất cả các phương thức lớp Dogđược chỉ định bởi công cụ sửa đổi public. Nghĩa là, chúng ta có thể gọi chúng từ bất kỳ lớp nào khác:
public class Main {

   public static void main(String[] args) {

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

}
Các phương thức lớp Dog, như bạn có thể thấy, có thể truy cập dễ dàng trong lớp đó Main. Điều này có thể thực hiện được nhờ vào công cụ sửa đổi public. Có các công cụ sửa đổi khác trong Java và không phải tất cả chúng đều cho phép bạn sử dụng một phương thức bên trong một lớp khác. Chúng tôi sẽ nói về chúng trong các bài giảng khác. Điều chính là phải nhớ những gì công cụ sửa đổi chịu trách nhiệm: tính khả dụng/không thể truy cập của phương thức trong các lớp khác :)

2. Từ khóa tĩnh

Một trong những phương pháp Dog, cụ thể là, main()được biểu thị bằng từ khóa static. Nếu nó tồn tại thì nó phải được chỉ định sau bộ sửa đổi truy cập. Bạn có nhớ trong các bài giảng trước chúng ta đã nói về các biến lớp tĩnh không? Khi áp dụng cho các phương thức, từ này có ý nghĩa gần giống nhau. Nếu một phương thức được chỉ định là static, điều này có nghĩa là nó có thể được sử dụng mà không cần tham chiếu đến một đối tượng lớp cụ thể. Và thực tế, để chạy một phương thức tĩnh main()trong một lớp, Dogbạn không cần tạo một cá thể Dog; nó chạy mà không cần nó. Nếu phương thức này không tĩnh thì để sử dụng nó trước tiên chúng ta cần tạo một đối tượng.

3. Giá trị trả về.

Nếu phương thức của chúng ta phải trả về một cái gì đó thì chúng ta sẽ chỉ ra loại giá trị trả về. Điều này có thể được nhìn thấy trong ví dụ về getter getName():
public String getName() {
   return name;
}
Nó trả về một đối tượng thuộc loại String. Nếu phương thức không trả về bất cứ thứ gì, thì từ khóa sẽ được chỉ định thay vì loại void, như trong phương thức woof():
public void woof() {
   System.out.println("Собака по имени " + name + " говорит \"Гав-гав!\"");
}

Các phương thức có cùng tên

Có những tình huống khi chương trình của chúng tôi yêu cầu một số tùy chọn về cách hoạt động của một phương thức. Tại sao chúng ta không tạo ra trí tuệ nhân tạo của riêng mình? Amazon có Alexa, Yandex có Alice, vậy tại sao chúng ta lại tệ hơn? :) Trong bộ phim về Iron Man, Tony Stark đã tạo ra trí thông minh nhân tạo xuất sắc của riêng mình - JARVIS Hãy cùng vinh danh nhân vật tuyệt vời này và đặt tên AI của chúng ta để vinh danh anh ấy :) The điều đầu tiên chúng ta phải dạy Jarvis - chào hỏi những người bước vào phòng (thật lạ nếu một trí tuệ tuyệt vời như vậy lại trở nên bất lịch sự).
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");
   }
}
Đầu ra của bảng điều khiển:

Добрый вечер, Тони Старк, How ваши дела?
Tuyệt vời! Jarvis biết cách chào đón người bước vào. Tất nhiên, thông thường nhất sẽ là chủ nhân của anh ấy - Tony Stark. Nhưng anh ấy có thể không đến một mình! Và phương thức của chúng tôi sayHi()chỉ lấy một đối số làm đầu vào. Và theo đó, anh ta sẽ chỉ có thể chào một trong số những người đến và sẽ phớt lờ những người còn lại. Không lịch sự lắm, đồng ý không?:/ Trong trường hợp này, để giải quyết vấn đề, chúng ta chỉ cần viết 2 phương thức trong lớp có cùng tên nhưng có tham số khác nhau:
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?");
   }

}
Điều này được gọi là nạp chồng phương thức . Quá tải cho phép chương trình của chúng tôi linh hoạt hơn và đáp ứng các tùy chọn công việc khác nhau. Hãy kiểm tra xem nó hoạt động như thế nào:
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");
   }
}
Đầu ra của bảng điều khiển:

Добрый вечер, Тони Старк, How ваши дела? 
Добрый вечер, Тони Старк, Капитан Америка, How ваши дела?
Tuyệt vời, cả hai lựa chọn đều hoạt động :) Tuy nhiên, chúng tôi không giải quyết được vấn đề! Nếu có ba khách thì sao? Tất nhiên, chúng ta có thể nạp chồng lại phương thức sayHi()để chấp nhận tên của ba khách. Nhưng có thể có 4 hoặc 5 người trong số họ, và cứ thế đến vô tận. Có cách nào khác để dạy Jarvis làm việc với bất kỳ số lượng tên nào mà không bị quá tải hàng triệu phương thức không sayHi()? :/ Tất nhiên là có! Nếu không thì liệu Java có phải là ngôn ngữ lập trình phổ biến nhất thế giới không? ;)
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");
   }
}
Bản ghi ( String...names) được truyền dưới dạng tham số cho phép chúng ta chỉ ra rằng một số chuỗi nhất định được truyền cho phương thức. Chúng tôi không chỉ định trước nên có bao nhiêu, vì vậy hoạt động của phương thức của chúng tôi giờ đây trở nên linh hoạt hơn nhiều:
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");
   }
}
Đầu ra của bảng điều khiển:

Добрый вечер, Тони Старк, How ваши дела? 
Добрый вечер, Капитан Америка, How ваши дела? 
Добрый вечер, Черная Вдова, How ваши дела? 
Добрый вечер, Халк, How ваши дела?
Bên trong phương thức, chúng ta lặp qua tất cả các đối số và xuất các cụm từ có sẵn có tên ra bảng điều khiển. Ở đây chúng tôi sử dụng một vòng lặp đơn giản hóa for-each(bạn đã gặp nó rồi). Thật tuyệt vời vì việc viết String...namesthực sự có nghĩa là tất cả các tham số đã truyền sẽ được trình biên dịch đưa vào một mảng. Do đó, namesbạn có thể làm việc với một biến như với một mảng, bao gồm cả việc lặp qua biến đó. Hơn nữa, nó sẽ hoạt động với bất kỳ số lượng dòng được chuyển nào! Hai, mười, thậm chí một nghìn - phương pháp này sẽ hoạt động đáng tin cậy với bất kỳ số lượng khách nào. Thuận tiện hơn nhiều so với việc nạp chồng tất cả các tùy chọn có thể, bạn có đồng ý không? :) Hãy đưa ra một ví dụ khác về nạp chồng phương thức. Hãy thêm một phương thức vào Jarvis printInfoFromDatabase(). Nó sẽ in thông tin về người đó từ cơ sở dữ liệu đến bảng điều khiển. Nếu cơ sở dữ liệu chỉ ra rằng một người là siêu anh hùng hoặc siêu phản diện, thông tin này cũng sẽ được hiển thị trên màn hình:
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, "Магнето");
   }
}
Phần kết luận:

Лора Палмер. Дата рождения - 22 июля 1972, город Твин Пикс, штат Washington
Макс Эйзенхарт. Рост 188см, вес 86 кг 
Также известен How суперзлодей Магнето
Đây là cách phương thức của chúng tôi hoạt động tùy thuộc vào dữ liệu chúng tôi truyền vào nó. Một điểm quan trọng khác:Thứ tự của các đối số quan trọng! Giả sử phương thức của chúng ta lấy một chuỗi và một số làm đầu vào:
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!
   }
}
Nếu một phương thức sayYourAge()lớp Manlấy một chuỗi và một số làm đầu vào thì đây là thứ tự chúng cần được truyền vào chương trình! Nếu chúng ta chuyển chúng theo một thứ tự khác, trình biên dịch sẽ báo lỗi và người đó sẽ không thể biết được tuổi của mình. Nhân tiện, các hàm tạo mà chúng ta đề cập trong bài giảng trước cũng là các phương thức! Chúng cũng có thể bị quá tải (tạo một số hàm tạo với các bộ đối số khác nhau) và đối với chúng, thứ tự truyền đối số về cơ bản cũng rất quan trọng. Phương pháp thực sự! :)

Cách gọi các phương thức có tham số tương tự

Như bạn đã biết, trong Java có một từ như null. Khi làm việc với nó, điều quan trọng là phải hiểu rằng null không phải là một đối tượng cũng không phải là một kiểu dữ liệu. Hãy tưởng tượng chúng ta có một lớp Man và một phương thức introduce()khai báo tên và tuổi của một người. Trong trường hợp này, tuổi có thể được truyền tải dưới dạng văn bản hoặc có thể được biểu thị dưới dạng số.
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);
   }
}
Chúng ta đã quen với việc nạp chồng nên chúng ta biết rằng phương thức này sẽ hoạt động như mong đợi cả hai lần:

Меня зовут Саша, мой возраст - двадцать один 
Меня зовут Мария, мой возраст - 32 
Nhưng điều gì sẽ xảy ra nếu chúng ta truyền null làm tham số thứ hai, không phải chuỗi hay số?
public static void main(String[] args) {

   Man victor = new Man();
   victor.introduce("Виктор", null);//Ambiguous method call!
}
Chúng ta sẽ gặp lỗi biên dịch! Lỗi “Cuộc gọi phương thức mơ hồ” được dịch là “cuộc gọi phương thức mơ hồ”. Tại sao nó có thể phát sinh và “sự mơ hồ” là gì? Nó thực sự đơn giản. Vấn đề là, chúng ta có hai biến thể của phương thức: with Stringvà with Integerlàm đối số thứ hai. Nhưng cả hai Stringvà đều Integercó thể rỗng! Đối với cả hai loại (vì chúng là loại tham chiếu), null là giá trị mặc định. Đó là lý do tại sao trình biên dịch trong tình huống này không thể tìm ra phiên bản nào của phương thức mà nó sẽ gọi. Giải quyết vấn đề này khá đơn giản. Vấn đề là null có thể được chuyển đổi rõ ràng thành một loại tham chiếu cụ thể. Do đó, khi gọi một phương thức, bạn có thể chỉ ra trong ngoặc đơn loại dữ liệu bạn cần cho đối số thứ hai! Trình biên dịch sẽ hiểu “gợi ý” của bạn và gọi phương thức được yêu cầu:
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);
   }
}
Phần kết luận:

Метод с двумя строками! 
Меня зовут Виктор, мой возраст - null
Nhưng nếu tham số số là nguyên thủy intvà không phải là đối tượng thuộc loại tham chiếu Integerthì lỗi như vậy sẽ không xảy ra.
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);
   }
}
Bạn có đoán được tại sao không? Nếu bạn đoán được thì làm tốt lắm :) Vì nguyên thủy không thể bằng null. Bây giờ trình biên dịch chỉ có một tùy chọn để gọi phương thức introduce()- với hai dòng. Phiên bản này của phương thức sẽ được xử lý mỗi khi phương thức được gọi.
Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION