2011-07-06 29 views
30
class ThrowNull { 
    public static void main(String[] args) { 
     throw null; 
    } 
} 

Chúng tôi biết rằng quy tắc để ném là throw ThrowableInstance;, trong đó ThrowableInstance phải là một đối tượng thuộc loại Có thể ném hoặc một lớp con của Throwable.Tại sao "ném null" không tạo ra lỗi biên dịch trong Java?

Các loại đơn giản, chẳng hạn như int hoặc char, cũng như các lớp không thể ném, chẳng hạn như String và Object, không thể được sử dụng làm ngoại lệ. null là một chữ Java đặc biệt đại diện cho một giá trị null.

Vậy tại sao throw null; sẽ biên dịch mã này?

+3

Tại sao nó dẫn đến lỗi biên dịch? – BoltClock

+0

Mặc dù điều này không được đánh dấu là một vấn đề của Java Compiler tại thời điểm hiện tại (trừ khi đặc tả ngôn ngữ thay đổi tại một thời điểm nào đó trong tương lai), rõ ràng là một ứng cử viên cho các trình kiểm tra tĩnh như "Sonar" để root và chỉ ra nhà phát triển. Có lẽ nhà phát triển muốn viết "return null" ... –

+2

Chúng ta biết rằng quy tắc là kết quả của việc gọi 'String a() {return null}' phải là một đối tượng của lớp (sub) hoặc String. Các lớp đơn giản, như Throwable hoặc BigInteger không thể được sử dụng như Strings. Null là một chữ Java đặc biệt đại diện cho một giá trị null.Vậy tại sao 'return null' lại không tạo ra bất kỳ lỗi thời gian biên dịch nào ????? !!!! Tôi đang vạch trần các tiêu chuẩn kép của bạn ở đây. Tại sao bạn phàn nàn về 'ném null' nhưng không phải về' trả về null'? Tôi không thể upvote câu hỏi của bạn do đó. Nó quá địa phương hóa bằng các tiêu chuẩn kép. – Val

Trả lời

54

Theo language specification, một tuyên bố throw được định nghĩa là:

throw Expression 

Và nếu Expression đánh giá để null, sau đó một NullPointerException được ném. Cụ thể,

Nếu đánh giá của Biểu hoàn bình thường, tạo ra một giá trị null, sau đó một thể hiện V' của lớp NullPointerException được tạo ra và ném thay vì null.

Mở rộng mở rộng RuntimeException, đây là một ngoại lệ không được kiểm soát. Điều này có thể giải thích tại sao không có lỗi biên dịch được báo cáo từ cấu trúc này.

5

Có rất nhiều thứ mà trình biên dịch không kiểm tra, nó giả định bạn làm mọi thứ vì một lý do chính đáng mà nó có thể không biết. Những gì nó cố gắng ngăn chặn là những sai lầm phổ biến mà các nhà phát triển mắc phải.

Có thể một số ai nghĩ rằng đây là một bàn tay tốt ngắn cho

throw new NullPointerException(); 

Integer i = null; 
try { 
    i.intValue(); 
} catch (NullPointerException npe) { 
    System.err.println("Caught NPE"); 
    npe.printStackTrace(); 
} 

try { 
    throw null; 
} catch (NullPointerException npe) { 
    System.err.println("Caught NPE"); 
    npe.printStackTrace(); 
} 

in trong Java 6 update 38

Caught NPE 
java.lang.NullPointerException 
    at Main.main(Main.java:9) 
+0

@DanielWerner Tất cả ngoại lệ và lỗi và có thể bắt được ngay cả OutOfmemoryError và ThreadDeath. ;) Xem ví dụ của tôi. –

2

Trong generel, và không chỉ ném. Bất kỳ biến đối tượng nào đều có thể được gán null. Vì vậy, chúng ta có thể thấy rằng ném không phải là một trường hợp đặc biệt. Nó phải được? có lẽ. Nó có nhất quán không? Vâng.

3

Tôi nghĩ vì Null có thể được truyền vào bất kỳ loại tham chiếu nào. Trong thời gian biên dịch, không có gì sai nếu bạn đang ném null thay vì ném.

+0

Chính xác. Phương thức của bạn, trả về một String, có thể trả về null. Tại sao biến chuỗi có thể là null nhưng biến Throwable không thể? OP chắc chắn là ngắn hạn (x) hoặc thực hiện các tiêu chuẩn kép. – Val

+0

Điều này nghe có vẻ độc đáo, nhưng điều đó không đúng. Xem câu trả lời được chấp nhận. – Vlasec

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