2014-10-03 13 views
5

Xin xem Java Class nàyGọi dường như mơ hồ, nhưng chạy một cách hoàn hảo với sản lượng bất ngờ

class Demo 
{ 
    public static void a(String s) 
    { 
     System.out.println("string called"); 
    } 
    public static void a(Object a) 
    { 
     System.out.println("Object called"); 
    } 
    public static void main(String...asrgs) 
    { 
     a(null); 
    } 
} 

Kết quả của mã này là "chuỗi gọi là" nhưng tôi không thể hiểu rằng cách trình biên dịch có thể giải quyết giữa Đối tượngChuỗi.

Hơn nữa, kiểm tra đoạn mã này

class Demo 
{ 
    public static void a(String s) 
    { 
     System.out.println("string called"); 
    } 
    public static void a(Integer n) 
    { 
     System.out.println("number called"); 
    } 
    public static void a(Object a) 
    { 
     System.out.println("Object called"); 
    } 
    public static void main(String...asrgs) 
    { 
     a(null); 
    } 
} 

Ở đây chúng ta nhận được một lỗi thời gian biên dịch liên quan đến cuộc gọi mơ hồ (đó là khá rõ ràng). Bất kỳ giải thích tốt cho điều này?

+0

Giải thích cho lần đầu tiên hoặc giây giới? –

+1

cả hai, nếu có thể :) – Gagan93

Trả lời

5

Câu trả lời nằm trong §15.12.2 của JLS:

Bước thứ hai tìm kiếm kiểu xác định trong bước trước cho các phương pháp thành viên. Bước này sử dụng tên của phương thức và các biểu thức đối số để định vị các phương thức có thể truy cập và áp dụng được, đó là các khai báo có thể được gọi đúng trên các đối số đã cho.

Có thể có nhiều phương pháp như vậy, trong trường hợp này là loại cụ thể nhất được chọn. Bộ mô tả (chữ ký cộng với kiểu trả về) của phương thức cụ thể nhất là phương thức được sử dụng trong thời gian chạy để thực hiện việc gửi phương thức.

(tôi nhấn mạnh)

... và §15.12.2.5, mà phần trên đề cập đến, trong đó có chi tiết đầy đủ các quy tắc đặc hiệu, mà còn tóm tắt tiện dụng này:

Trực giác không chính thức là một phương thức cụ thể hơn một phương thức khác nếu bất kỳ lời gọi nào được xử lý bởi phương thức đầu tiên có thể được truyền sang phương thức khác mà không có lỗi biên dịch.

Trong ví dụ đầu tiên, a(String) cụ thể hơn a(Object), vì vậy trình biên dịch sẽ biết cái nào cần sử dụng và vui. Trong ví dụ thứ hai của bạn, cả hai a(String)a(Integer) thì đặc biệt hơn a(Object), nhưng một trong hai là áp dụng đối với null và họ đang ở trong dòng riêng biệt (StringString > Object, IntegerInteger > Number > Object), tạo ra sự nhập nhằng trình biên dịch phàn nàn về.

Nếu họ ở trong dòng cùng một dòng, sẽ không có sự mơ hồ, bởi vì sẽ có một tùy chọn cụ thể nhất có thể áp dụng. Ví dụ:

class Base { 
} 
class Child extends Base { 
} 
class GrandChild extends Child { 
} 
public class Example { 

    public static final void main(String[] args) { 
     a(null); 
    } 

    public static void a(Base b) { 
     System.out.println("Base"); 
    } 

    public static void a(Child b) { 
     System.out.println("Child"); 
    } 

    public static void a(GrandChild b) { 
     System.out.println("GrandChild"); 
    } 
} 

Đó in "GrandChild", bởi vì trong khi cả hai a(Child)a(GrandChild) thì đặc biệt hơn a(Object), a(GrandChild) là cụ thể hơn so a(Child).

Các vấn đề liên quan