"Xin chào, Amigo! Vài ngày trước tôi đã nói với bạn về các phương pháp nạp chồng. Bạn đã hiểu hết chưa?"

"Vâng. Tôi nhớ. Mỗi phương thức của lớp phải là duy nhất. Một phương thức thành viên là duy nhất nếu lớp không có phương thức nào khác có cùng tên và loại tham số (và thứ tự của các tham số là quan trọng)."

"Rất tốt! Tôi thấy bạn đã học tốt bài học đó. Hôm nay tôi muốn mở rộng kiến ​​thức của bạn về chủ đề này một chút. Bạn nghĩ phương pháp nào sẽ được gọi trong mỗi trường hợp?"

Mã số
class Cat
{
 public static void print(int n)
 {
  System.out.println(n);
 }
 public static void print(short n)
 {
  System.out.println(n);
 }
 public static void print(Integer n)
 {
  System.out.println(n);
 }
 public static void print(String s)
 {
  System.out.println(s);
 }
public static void main(String[] args)
{
  Cat.print(1);
  Cat.print((byte)1);
  Cat.print("1");
  Cat.print(null);
 }
}

"Khó mà nói ra được."

"Trong trường hợp đầu tiên, 1 là một int . Chúng tôi có một kết quả khớp 100% với phương thức lấy một int. Bản in void(int n) đầu tiên sẽ được gọi.

Trong trường hợp thứ hai, chúng ta không có phương thức lấy một byte. Nhưng có hai phương pháp mất một đoạn ngắn và một đoạn mã int. Dựa trên các quy tắc mở rộng loại, trước tiên một byte sẽ được mở rộng thành short, sau đó được mở rộng thành int. Vì vậy, phán quyết là void print(n ngắn). sẽ được gọi.

Trong trường hợp thứ ba, chúng tôi có kết quả khớp 100% với phương thức lấy Chuỗi. Bản in void(String s). phương thức sẽ được gọi.

Trường hợp thứ tư là mơ hồ. null không có loại cụ thể. Trình biên dịch sẽ từ chối biên dịch mã này . Trong trường hợp này, chúng ta cần viết Cat.print((Integer)null) để gọi phương thức thứ ba và Cat.print((String)null) để gọi phương thức thứ tư."

"Đó là thông tin rất hữu ích. Cảm ơn bạn."

"Tôi muốn chỉ ra rằng khi xác định phương pháp chính xác để gọi, các loại chỉ có thể mở rộng. Chúng không thể thu hẹp. Hãy xem xét ví dụ này:"

Mã số
class Cat
{
 public static void print(short n)
 {
  System.out.println(n);
 }
 public static void print(Integer n)
 {
  System.out.println(n);
 }

 public static void main(String[] args)
 {
  Cat.print((byte)1);
  Cat.print(1);
 }
}

Trong trường hợp đầu tiên, kiểu byte sẽ được mở rộng thành short và phương thức đầu tiên sẽ được gọi: void print(short n). .

Trong trường hợp thứ hai, sẽ có một chuyển đổi mở rộng ngầm định từ int sang Integer, và khi đó phương thức thứ hai sẽ được gọi là: void print(Integer n). .

"Tôi không mong đợi điều đó."

"Không, đây mới là điều ngạc nhiên thực sự:"

mã Java Sự miêu tả
 class Cat
{
 public static void print(Object o)
 {
  System.out.println(o);
 }
 public static void print(String s)
 {
  System.out.println(s);
 }

 public static void main(String[] args)
 {
  Cat.print(1);
  Cat.print(null);
 }
}
Trong trường hợp đầu tiên, int sẽ được mở rộng thành Integer. Bởi vì không có phương thức nào cho Integer, phương thức phù hợp nhất (và phương thức được gọi) là void print(Object o)

Trong trường hợp thứ hai, sẽ không có bất kỳ lỗi biên dịch nào và void print(String s) sẽ được gọi, điều này hơi khó hiểu.

"Anh bạn, tôi hy vọng bạn hiểu rằng trong những trường hợp như vậy, tốt nhất là chỉ định một toán tử ép kiểu (như chúng ta đã làm với «(byte)») để biết chính xác phương thức nào sẽ được gọi."

"Tôi chưa bao giờ mong đợi bất kỳ vấn đề nào sẽ đến từ việc quá tải các phương pháp. Nhưng rồi bạn cũng đến. Cảm ơn, Rishi. Tôi sẽ tiếp tục cảnh giác về điểm này."