2012-04-10 31 views
16
public class Main 
{ 
    public static void main(String []ar) 
    { 
     A m = new A(); 
     System.out.println(m.getNull().getValue()); 
    } 
} 

class A 
{ 
    A getNull() 
    { 
     return null; 
    } 

    static int getValue() 
    { 
     return 1; 
    } 
} 

Tôi đã xem qua câu hỏi này trong một cuốn sách SCJP. Mã này in ra 1 thay vì một NPE như mong đợi. Ai đó có thể giải thích lý do cho cùng?Tại sao mã này KHÔNG trả về một NullPointerException?

Trả lời

18

Nó hoạt động như nó phải theo Java Language Specification:

một tham chiếu null có thể được sử dụng để truy cập vào một (tĩnh) biến lớp học mà không gây ra một ngoại lệ.

22

Về cơ bản, bạn đang gọi phương thức tĩnh như thể đó là phương pháp thể hiện. Mà chỉ được giải quyết đến một phương pháp gọi tĩnh, vì vậy, nếu như bạn đã viết:

A m = new A(); 
m.getNull(); 
System.out.println(A.getValue()); 

IMO thực tế là mã của bạn là hợp pháp ở tất cả là một lỗ hổng thiết kế trong Java. Nó cho phép bạn viết mã rất gây hiểu nhầm, với Thread.sleep làm ví dụ tôi luôn sử dụng:

Thread thread = new Thread(someRunnable); 
thread.start(); 
thread.sleep(1000); 

Chủ đề nào gửi đến chế độ ngủ? Mục hiện tại, "tất nhiên" ...

6

Cuộc gọi phương thức tĩnh được giải quyết tại thời gian biên dịch. Trình biên dịch thấy rằng getNull() có giá trị trả về loại A có phương thức tĩnh getValue() (và không có phương thức thể hiện cùng tên), do đó, trong mã byte, giá trị trả về thực tế là getNull() bị bỏ qua và gọi là A.getValue().

1

Hàm getNull trả về đối tượng A. getValue được khai báo là tĩnh và chỉ cần class_name hoạt động, như trong A.getValue(). Bởi vì getNull trả về (trên thực tế) một đối tượng A ... bạn sẽ nhận được 1

1

System.out.println (m.getNull(). GetValue()); dòng mã này giống như System.out.println (A.getValue());

như vì getValue() phương pháp là tĩnh và và tất cả các cuộc gọi tĩnh khởi tại thời gian biên dịch trong java. do đó, nó không tạo ra bất kỳ lỗi nào khi bạn tạo getValue() không tĩnh sẽ tạo ra lỗi vì nó sẽ được gọi vào thời gian chạy

+1

Điều này không đúng, 'm.getNull()' ** không ** được gọi. Xem câu trả lời của Jon. – assylias

+0

m.getNull() sẽ chỉ được gọi nếu getNull không tĩnh. mà tôi đã đề cập trước đó. –

+1

Ý tôi là 'System.out.println (m.getNull(). GetValue());' không tương đương với 'System.out.println (A.getValue());'. Nó tương đương với 'm.getNull(); System.out.println (A.getValue()); '. – assylias

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