2008-12-18 35 views
12

Tại sao nó (rõ ràng) tạo sự khác biệt cho dù tôi chuyển trực tiếp null làm đối số hoặc chuyển Object mà tôi đã gán giá trị null?Phương thức Java gửi với đối số rỗng

Object testVal = null; 
test.foo(testVal); // dispatched to foo(Object) 
// test.foo(null); // compilation problem -> "The method foo(String) is ambiguous" 

public void foo(String arg) { // More-specific 
    System.out.println("foo(String)"); 
} 

public void foo(Object arg) { // Generic 
    System.out.println("foo(Object)"); 
} 

Nói cách khác, tại sao lại là (nhận xét-out) gọi thứ hai để foo(...) không cử đến foo(Object)?

Cập nhật: Tôi sử dụng Java 1.6. Tôi có thể biên dịch mã của Hemal mà không có vấn đề gì, nhưng tôi vẫn không biên dịch. Sự khác biệt duy nhất tôi thấy là phương pháp của Hemal là tĩnh trong khi tôi thì không. Nhưng tôi thực sự không hiểu tại sao điều này lại tạo nên sự khác biệt ...?

Cập nhật 2: Đã giải quyết. Tôi đã có một phương thức khác (Runnable) trong lớp của tôi, do đó người điều phối không thể chọn một cách rõ ràng phương thức cụ thể nhất. (Xem bình luận của tôi trong câu trả lời thứ hai của Hemal.) Cảm ơn tất cả mọi người đã giúp đỡ của bạn.

Trả lời

24

Bạn đang sử dụng phiên bản Java nào? Với mã 1.6.0_11 (được dán bên dưới) biên dịch và chạy.

Tôi chắc chắn rõ ràng lý do tại sao foo(testVal) chuyển đến foo(Object).

Lý do tại sao foo(null) chuyển đến foo(String) là một chút phức tạp. Hằng số null là loại nulltype, là loại phụ của tất cả các loại. Vì vậy, điều này nulltype kéo dài String, mở rộng Object.

Khi bạn gọi foo(null) trình biên dịch tìm kiếm phương thức quá tải với loại cụ thể nhất. Vì String cụ thể hơn, Object là phương thức được gọi.

Nếu bạn có một tình trạng quá tải khác cụ thể như Chuỗi, giả sử foo(Integer) thì bạn sẽ nhận được lỗi quá tải không rõ ràng.

class NullType { 

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

    static void foo() 
    { 
    Object testVal = null; 
    foo(testVal); // dispatched to foo(Object) 
    foo(null); // compilation problem -> "The method foo(String) is ambiguous" 
    } 

    public static void foo(String arg) { // More-specific 
    System.out.println("foo(String)"); 
    } 

    public static void foo(Object arg) { // Generic 
    System.out.println("foo(Object)"); 
    } 

} 
+0

Chỉ cần kiểm tra điều này và tôi choáng váng rằng (a) 6u11 không nói nó mơ hồ, và (b) null phân giải thành chuỗi không phải đối tượng. Tìm hiểu điều gì đó mới mỗi ngày - +1 cho bài học. –

+1

@Software Monkey: Một khi bạn chấp nhận rằng null không đổi là kiểu null và kiểu null là một kiểu con của tất cả các kiểu, điều này khá rõ ràng. Đối tượng

+0

Pedantry: phương thức ghi đè đối tượng bằng chuỗi. Quá tải là nơi tên phương thức giống nhau nhưng chữ ký thay đổi rộng rãi hơn. Câu trả lời tuyệt vời. Cám ơn. – Sam

2

Vì người thứ hai nhận xét lời gọi với null là mơ hồ đối với trình biên dịch. Chữ số rỗng có thể là một chuỗi hoặc một đối tượng. Trong khi giá trị được gán có một loại xác định. Bạn cần bỏ giá trị rỗng, ví dụ: test.foo ((String) null) để loại bỏ sự mơ hồ.

1

Có ai đã thử ví dụ này không ???

Với 1.6.0 foo (null) được cử đến các phương pháp cụ thể nhất được áp dụng đó là foo (String) ...

Nếu bạn thêm một phương pháp mới nói foo (Integer) trình biên dịch không thể chọn nhiều nhất phương pháp áp dụng cụ thể và hiển thị lỗi.

-Patrick

1

Xin lỗi để sử dụng câu trả lời, nhận xét nhưng tôi cần đăng mã không phù hợp với nhận xét.

@Yang, tôi cũng có thể biên dịch và chạy như sau. Bạn có thể đăng một mã hoàn chỉnh biên dịch với một dòng nhận xét sao cho nếu tôi bỏ ghi chú dòng đó thì nó sẽ không biên dịch?

class NullType { 

    public static final void main(final String[] args) { 
    foo(); 
    new Test().bar(new Test()); 
    } 

    static void foo() 
    { 
    Object testVal = null; 
    foo(testVal); // dispatched to foo(Object) 
    // foo(null); // compilation problem -> "The method foo(String) is ambiguous" 
    } 

    public static void foo(String arg) { // More-specific 
    System.out.println("foo(String)"); 
    } 

    public static void foo(Integer arg) { // More-specific 
    System.out.println("foo(Integer)"); 
    } 

    public static void foo(Object arg) { // Generic 
    System.out.println("foo(Object)"); 
    } 


} 


class Test 
{ 
    void bar(Test test) 
    { 
    Object testVal = null; 
    test.foo(testVal); // dispatched to foo(Object) 
    test.foo(null); // compilation problem -> "The method foo(String) is ambiguous" 
    } 

    public void foo(String arg) { // More-specific 
    System.out.println("foo(String)"); 
    } 

    public void foo(Object arg) { // Generic 
    System.out.println("foo(Object)"); 
    } 
} 
+0

Huh, tôi đã dọn dẹp lớp thử nghiệm của mình để đăng nó ở đây và nhận ra rằng ngoài foo (String) và foo (Object), tôi cũng có một foo (Runnable) - cái mà bây giờ tôi hiểu là foo (null) không rõ ràng vì String không cụ thể hơn Runnable và ngược lại. Cảm ơn Hemal vì sự giúp đỡ quý giá của bạn! –

+0

Vui vì tôi đã có thể giúp đỡ. Không có chi. –

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