CodeGym /Blog Java /Ngẫu nhiên /khai báo phương thức

khai báo phương thức

Xuất bản trong nhóm
CHÀO! Bạn đã biết về cách tạo các lớp của riêng mình với các trường và phương thức. Bây giờ chúng ta sẽ tập trung vào các phương pháp.
Khai báo phương thức - 1
Tất nhiên, chúng tôi đã làm điều này hơn một lần trong các bài học của mình, nhưng chúng tôi chủ yếu đề cập đến những điều chung chung. Hôm nay, chúng ta sẽ mổ xẻ các phương pháp và nghiên cứu xem chúng được tạo ra từ đâu, các cách khác nhau để tạo ra chúng và cách quản lý tất cả. :) Đi nào!

khai báo phương thức

Tất cả mã định nghĩa một phương thức được gọi là khai báo phương thức . Hình thức chung của một khai báo phương thức có thể được mô tả như sau:

access modifier, return type, method name (parameter list) {
    // method body
}
Để làm ví dụ, hãy xem các khai báo của các phương thức khác nhau 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("A dog named " + name + " says \"Woof, woof!\"");
   }

   public void run(int distanceInFeet) {
       System.out.println("A dog named " + name + " ran " + distanceInFeet + " feet!");
   }

   public String getName() {
       return name;
   }
}

1. Công cụ sửa đổi truy cập

Công cụ sửa đổi truy cập luôn được chỉ định đầu tiên. Tất cả Dogcác phương thức của lớp được đánh dấu bằng công cụ sửa đổi công khai . Điều này có 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");
       butch.run(100);
   }

}
Như bạn có thể thấy, Dogcác phương thức của lớp được truy cập dễ dàng trong Mainlớp. Điều này có thể là do công cụ sửa đổi công khai . Trong Java, có các công cụ sửa đổi khác. Tất cả chúng không cho phép sử dụng các phương thức trong các lớp khác. Chúng ta sẽ nói về chúng trong các bài học khác. Điều chính cần nhớ là công cụ sửa đổi chịu trách nhiệm về điều gì: liệu một phương thức có thể truy cập được trong các lớp khác hay không :)

2. từ khóa tĩnh

Một trong Dogcác phương thức, main(), được đánh dấu bằng từ khóa tĩnh . Nó cũng là một phần của khai báo phương thức, và chúng ta đã biết ý nghĩa của nó. Chúng tôi đã không đề cập đến nó trong mẫu khai báo phương thức được đưa ra ở đầu bài học, bởi vì nó là tùy chọn. Nếu nó được chỉ định, thì nó phải xuất hiện sau công cụ sửa đổi truy cập. Hãy nhớ rằng trong những bài học gần đây chúng ta đã nói về các biến (lớp) tĩnh? Khi được áp dụng cho các phương thức, từ khóa này có ý nghĩa gần giống nhau. Nếu một phương thức là tĩnh , thì nó có thể được sử dụng mà không cần tham chiếu đến một đối tượng cụ thể của lớp. Và thực sự, bạn không cần một Dogđối tượng để chạy main()phương thức tĩnh trongDoglớp học. Nó sẽ chạy tốt mà không cần một. Nếu phương thức này không tĩnh, thì trước tiên chúng ta cần tạo một đối tượng để chạy nó.

3. Giá trị trả về

Nếu phương thức của chúng tôi sẽ trả về một cái gì đó, thì chúng tôi chỉ định loại giá trị trả về. Điều này là hiển nhiên từ ví dụ về getName()getter:

public String getName() {
   return name;
}
Nó trả về một Stringđối tượng. Nếu một phương thức không trả về bất cứ thứ gì, thì từ khóa void sẽ được sử dụng để thay thế, như trong woof()phương thức:

public void woof() {
   System.out.println("A dog named " + name + " says \"Woof, woof!\"");
}

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

Có những tình huống khi chúng ta muốn có nhiều cách khác nhau để gọi một phương thức. Tại sao không tạo ra trí tuệ nhân tạo của riêng chúng ta? Amazon có Alexa, Apple có Siri, vậy tại sao chúng ta không có? :) Trong phim Iron Man, Tony Stark tạo ra trí thông minh nhân tạo đáng kinh ngạc của riêng mình, Jarvis. Hãy vinh danh nhân vật tuyệt vời đó và đặt tên cho AI của chúng ta để vinh danh anh ấy. :) Điều đầu tiên chúng ta cần làm là dạy Jarvis chào những người bước vào phòng (sẽ thật kỳ 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?");
   }

   public static void main(String[] args) {
       Jarvis jarvis = new Jarvis();
       jarvis.sayHi("Tony Stark");
   }
}
Đầu ra bảng điều khiển: Chào buổi tối, Tony Stark. Bạn có khỏe không? Rất tốt! Jarvis hiện đã có thể đón khách. Tất nhiên, thường xuyên hơn đó sẽ là chủ nhân của anh ta, Tony Stark. Nhưng nếu anh ấy không đến một mình thì sao! Nhưng sayHi()phương pháp của chúng tôi chỉ chấp nhận một đối số. Và do đó, nó chỉ có thể chào một người bước vào phòng, và sẽ phớt lờ người kia. Không lịch sự lắm, đồng ý chứ? :/ Trong trường hợp này, chúng ta có thể giải quyết vấn đề bằng cách viết 2 phương thức có cùng tên nhưng khác tham số:

public class Jarvis {

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

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

}
Điều này được gọi là nạp chồng phương thức . Quá tải phương thức cho phép chương trình của chúng tôi linh hoạt hơn và phù hợp với nhiều cách làm việc khác nhau. Hãy xem lại cách nó hoạt động:

public class Jarvis {

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

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

   public static void main(String[] args) {
       Jarvis jarvis = new Jarvis();
       jarvis.sayHi("Tony Stark");
       jarvis.sayHi("Tony Stark", "Captain America");
   }
}
Đầu ra bảng điều khiển: Chào buổi tối, Tony Stark. Bạn có khỏe không? Chào buổi tối, Tony Stark và Captain America. Bạn có khỏe không? Tuyệt vời, cả hai phiên bản đều hoạt động. :) Nhưng 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 sayHi()phương thức một lần nữa để nó chấp nhận ba tên khách. Nhưng có thể có 4 hoặc 5. Cho đến vô tận. Không có cách nào tốt hơn để dạy Jarvis xử lý bất kỳ số lượng tên nào mà không làm quá tải sayHi()phương thức một triệu lần()? :/ Tất nhiên là có! Nếu không, bạn có nghĩ Java sẽ là ngôn ngữ lập trình phổ biến nhất trên 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?");
       }
   }

   public static void main(String[] args) {
       Jarvis jarvis = new Jarvis();
       jarvis.sayHi("Tony Stark");
       System.out.println();
       jarvis.sayHi("Tony Stark", "Captain America");
   }
}
Khi ( String... names ) được sử dụng làm tham số, nó chỉ ra rằng một tập hợp các Chuỗi sẽ được truyền cho phương thức. Chúng tôi không phải chỉ định trước sẽ có bao nhiêu, vì vậy bây giờ phương pháp của chúng tôi 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?");
       }
   }

   public static void main(String[] args) {
       Jarvis jarvis = new Jarvis();
       jarvis.sayHi("Tony Stark", "Captain America", "Black Widow", "Hulk");
   }
}
Đầu ra bảng điều khiển: Chào buổi tối, Tony Stark. Bạn có khỏe không? Chào buổi tối, Đội trưởng Mỹ. Bạn có khỏe không? Chào buổi tối, Góa Phụ Đen. Bạn có khỏe không? Chào buổi tối, Hulk. Bạn có khỏe không? Bên trong phương thức, chúng tôi lặp lại tất cả các đối số và hiển thị các cụm từ được định dạng bằng tên. Ở đây chúng tôi sử dụng một for-eachvòng lặp đơn giản hóa (mà bạn đã thấy trước đây). Nó hoàn hảo ở đây, bởi vì ký hiệu ( Chuỗi... tên ) thực sự có nghĩa là trình biên dịch đặt tất cả các đối số được truyền vào một mảng. Kết quả là chúng ta có thể làm việc với tên biếnnhư chúng ta sẽ làm việc với một mảng, kể cả bằng cách lặp qua nó trong một vòng lặp. Ngoài ra, nó sẽ hoạt động với bất kỳ số lượng chuỗi đã truyền nào! Hai, mười, thậm chí một nghìn—phương pháp này sẽ hoạt động hiệu quả với bất kỳ số lượng khách nào. Bạn có nghĩ rằng thuận tiện hơn là nạp chồng phương thức cho tất cả các khả năng không? :) Đây là một ví dụ khác về nạp chồng phương thức. Hãy cho Jarvis một printInfoFromDatabase()phương pháp. Nó sẽ hiển thị thông tin về một người từ cơ sở dữ liệu. 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 ác nhân, thì chúng tôi sẽ hiển thị thông tin đó:

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("Also known as the superhero " + nickname);
       } else {
           System.out.println("Also known as the supervillain " + nickname);
       }
   }

   public static void main(String[] args) {
       Jarvis jarvis = new Jarvis();
       jarvis.printInfoFromDatabase("Laura Palmer. Date of birth: July 22, 1972. Twin Peaks, Washington");
       System.out.println();
       jarvis.printInfoFromDatabase("Max Eisenhardt. Height: 15.6 ft. Weight: 189 lbs. ", true, "Magneto");
   }
}
Đầu ra: Laura Palmer. Ngày sinh: 22 tháng 7 năm 1972. Twin Peaks, Washington Max Eisenhardt. Chiều cao: 15,6 ft. Cân nặng: 189 lbs. Còn được gọi là siêu tội phạm Magneto Vì vậy, hành vi của phương thức của chúng ta phụ thuộc vào dữ liệu mà chúng ta truyền cho nó. Đây là một điểm quan trọng khác: thứ tự của các đối số rất quan trọng! Giả sử phương thức của chúng ta nhận một Chuỗi và một số:

public class Person {

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

   public static void main(String[] args) {

       sayYourAge("My age is ", 33);
       sayYourAge(33, "My age is "); // Error!
   }
}
Nếu phương thức Personcủa lớp sayYourAge()lấy một chuỗi và một số làm đầu vào, thì đây là thứ tự mà các đối số này phải được truyền cho phương thức! Nếu chúng ta chuyển chúng theo một thứ tự khác, thì trình biên dịch sẽ báo lỗi và người đó sẽ không thể nói tuổi của mình. Nhân tiện, hàm tạo mà chúng ta đã đề cập trong bài trước cũng là phương thức! Bạn cũng có thể quá tải chúng (tức là tạo một số hàm tạo với các bộ tham số khác nhau) và thứ tự của các đối số được truyền về cơ bản cũng rất quan trọng đối với chúng. Chúng là nhữ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, nulllà một từ khóa trong Java. Điều rất quan trọng là phải hiểu rằng đó nullkhông phải là đối tượng cũng không phải là kiểu dữ liệu . Hãy tưởng tượng rằng chúng ta có một Personlớp và một introduce()phương thức thông báo tên và tuổi của người đó. Hơn nữa, tuổi có thể được thông qua dưới dạng văn bản hoặc số.

public class Person {

   public void introduce(String name, String age) {
       System.out.println("My name is " + name + ". My age is " + age);
   }

   public void introduce(String name, Integer age) {
       System.out.println("My name is " + name + ". My age is " + age);
   }

   public static void main(String[] args) {

       Person alex = new Person();
       alex.introduce ("Alex", "twenty-one");

       Person mary = new Person();
       mary.introduce("Mary", 32);
   }
}
Chúng ta đã quen thuộc với nạp chồng, vì vậy chúng ta biết rằng cả hai phương thức sẽ hoạt động như bình thường: Tên tôi là Alex. Tuổi của tôi là hai mươi mốt Tên tôi là Mary. Tuổi của tôi là 32 Nhưng điều gì sẽ xảy ra nếu chúng ta chuyển nulltham số thứ hai thay vì một chuỗi hoặc một số?

public static void main(String[] args) {

   Person victor = new Person();
   victor.introduce("Victor", null);// Ambiguous method call!
}
Chúng tôi sẽ nhận được một lỗi biên dịch! Điều gì gây ra điều này và chính xác thì "sự mơ hồ" là gì? Trên thực tế, tất cả đều rất đơn giản. Vấn đề là chúng ta có hai phiên bản của phương thức: một phiên bản có a Stringlàm đối số thứ hai và một phiên bản có an Integerlàm đối số thứ hai. Nhưng a Stringvà an Integerđều có thể là null! Bởi vì chúng là các loại tham chiếu, nulllà giá trị mặc định cho cả hai. Đó là lý do tại sao trong tình huống này, trình biên dịch 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 pháp cho vấn đề này khá đơn giản. Nullcó thể được chuyển đổi rõ ràng thành một loại tham chiếu cụ thể. Vì vậy, khi bạn gọi một phương thức, bạn có thể chỉ ra kiểu dữ liệu mà bạn muốn cho đối số thứ hai trong ngoặc đơn! Trình biên dịch sẽ hiểu "gợi ý" của bạn và sẽ gọi đúng phương thức:

public class Person {

   public void introduce(String name, String age) {
       System.out.println("Method with two strings!");
       System.out.println("My name is " + name + ". My age is " + age);
   }

   public void introduce(String name, Integer age) {
       System.out.println("Method with a string and a number!");
       System.out.println("My name is " + name + ". My age is " + age);
   }

   public static void main(String[] args) {

       Person victor = new Person();
       victor.introduce("Victor", (String) null);
   }
}
Đầu ra: Phương thức có hai chuỗi! Tên của tôi là Victor. Tuổi của tôi là null Lưu ý rằng nếu tham số số là một kiểu nguyên thủy int, chứ không phải là một thể hiện của kiểu tham chiếu Số nguyên, thì sẽ không xảy ra lỗi như vậy.

public class Person {

   public void introduce(String name, String age) {
       System.out.println("Method with two strings!");
       System.out.println("My name is " + name + ". My age is " + age);
   }

   public void introduce(String name, int age) {
       System.out.println("Method with a string and a number!!");
       System.out.println("My name is " + name + ". My age is " + age);
   }

   public static void main(String[] args) {

       Person victor = new Person();
       victor.introduce("Victor", null);
   }
}
Bạn có đoán được tại sao không? Nếu bạn đã đoán tại sao, làm tốt lắm! :) Bởi vì nguyên thủy không thể là null. Bây giờ trình biên dịch chỉ có một lựa chọn, tức là gọi introduce()phương thức có hai chuỗi. Đây là phiên bản của phương thức sẽ chạy 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