2011-01-17 52 views
13

Tôi đã nghe nói rằng bắt NullPointerException là một thực tế xấu, và tôi nghĩ rằng đó là hợp lý như vậy. Để cho các NullPointerException để tuyên truyền lên đầu sẽ cho phép phát hiện một cái gì đó đi sai. Nhưng nhiều lần tôi đã thấy nhiều người bạn của tôi bắt gặp trực tiếp Exception để họ không cần phải bận tâm về tất cả các loại ngoại lệ khác nhau có thể xảy ra trong mã ở trên. Đây có phải là một thực hành tốt? Các loại ngoại lệ nào khác là tốt nhất còn lại được giải quyết? Và bên cạnh đó nó cũng có ý nghĩa với tôi để xử lý NullPointerException trên một mã cụ thể mà chúng tôi chắc chắn về nguồn gốc của ngoại lệ. Vì vậy, khi nào ngoại lệ được xử lý và khi nào thì chúng không được xử lý? Và điều gì sẽ là danh sách ngoại lệ có thể được giải quyết tốt nhất?Nếu bắt ngoại lệ con trỏ null không phải là một thực hành tốt, là bắt ngoại lệ tốt nhất?

+3

"' Tôi đã nghe nói rằng việc bắt NullPointerException là một thực tế tồi tệ, và tôi nghĩ rằng nó là hợp lý như vậy. Cho phép NullPointerException tuyên truyền lên đầu sẽ cho phép phát hiện một cái gì đó đi sai' "không có ý nghĩa nhiều với tôi . Không phải là bạn khó hiểu 'bắt' với 'nuốt'? – leonbloy

+2

Không có gì sai khi bắt 'NullPointerException' và làm điều gì đó với nó. Điều này đi cho bất kỳ ngoại lệ. Ý tưởng chung là để nắm bắt các ngoại lệ có thể được xử lý và không bắt (bỏ qua) những thứ không thể xử lý được. Vì vậy, tôi phải không đồng ý với những gì bạn đã nghe. –

Trả lời

20

Xử lý ngoại lệ cho Pokemon không tốt. Đặc biệt, nếu đó là một khối trống và bạn chỉ đơn giản là nuốt chúng. Bạn có ngoại lệ được nhập cụ thể vì lý do chúng thực sự có nghĩa là những điều cụ thể trong các ngữ cảnh cụ thể (về cơ bản, chúng cho bạn biết điều gì đã xảy ra). Vì vậy, bằng cách bắt Exception bạn đang nói rằng bạn không quan tâm những ngoại lệ đó là gì và bạn không quan tâm điều gì đã xảy ra. Điều này có lẽ không phải là những gì bạn muốn.

Nói chung, khi ngoại lệ bắt làm theo các quy tắc:

  • Nào thì nên để xử lý các ngoại lệ ở cấp độ này? Nếu có thì hãy xử lý. Nếu không, sau đó tuyên truyền.
  • Cùng với quy tắc đầu tiên, "xử lý" cũng có thể có nghĩa là bắt, đóng gói và phát lại. Đây là cách ngăn chặn sự rò rỉ trừu tượng để người gọi phương thức của bạn không phải biết về việc triển khai cơ bản.
  • Khối catch trống không có nghĩa là bạn đã xử lý ngoại lệ. Đó gọi là "nuốt"; ít nhất, bạn muốn đăng nhập ngoại lệ. Đôi khi một ngoại lệ xảy ra thực sự là một phần của luồng logic của mã của bạn, và vì vậy bạn có thể muốn làm một cái gì đó đặc biệt (nhưng điều này là, tha thứ cho việc chơi chữ, ngoại lệ thay vì quy tắc. Tốt hơn là kiểm tra các tình huống gây ra ngoại lệ thay vì kết hợp chúng vào luồng logic của mã của bạn).

Bạn có thể dễ dàng kiểm tra giá trị rỗng trong mã của mình, vì vậy không cần phải nắm bắt rõ ràng ngoại lệ con trỏ null. Nó không có ý nghĩa để cho một NullPointerException xảy ra (và đó là thực hành xấu). Ngay cả khi bạn có một số mã ném một NullPointerException, và đó là mã mà bạn không kiểm soát và không thể sửa chữa, bạn nên xác định các tham số đầu vào gây ra NullPointerException và kiểm tra cụ thể cho chúng.

Một ngoại lệ khác mà bạn không nên bắt là IllegalArgumentException. Ngoại lệ này có nghĩa là bạn đã vượt qua trong một đối số không có ý nghĩa. Thay vì bắt ngoại lệ này, bạn nên kiểm tra rõ ràng các thông số đầu vào của mình để đảm bảo rằng chúng là thông minh và chúng không thể gây ra IllegalArgumentException.

+12

"Xử lý ngoại lệ cho Pokemon" là gì? –

+25

catch (Exception ex) {khi bạn muốn bắt tất cả. –

+0

"Xử lý ngoại lệ cho Pokemon": Gotta Catch 'Em All: D – tkr

5

Bạn chỉ nên bắt ngoại lệ nếu bạn có thể thêm một số giá trị bằng cách làm như vậy. Nếu không, bạn nên để nó chuyển cho người gọi.

NullPointerException thường là kết quả của lỗi trong mã của bạn. Làm thế nào bạn có thể sửa chữa một cách hợp lý điều này trong một khối catch?

Không bị làm phiền về Ngoại lệ không phải là thực tiễn tốt.

0

nếu bạn có một cách duyên dáng để xử lý ngoại lệ của bạn, rất hữu ích khi bắt nó, nếu không hy vọng rằng người gọi có một cách tốt đẹp để xử lý nó.

+1

Nếu không, cuối cùng, ngoại lệ có thể được ghi lại. –

1

Quy tắc chính về bắt ngoại lệ là bạn phải biết tại sao bạn làm điều này. Lớp ngoại lệ bị bắt trong trường hợp lập trình viên muốn xử lý lỗi chung và anh ta không thực sự quan tâm chính xác những gì đã xảy ra, điều chính là điều gì đó sai. Trong trường hợp đó, anh ta có thể quyết định giao dịch rollback hoặc thực hiện một số dọn dẹp. Nếu bạn đang bắt ngoại lệ cụ thể, hãy thử áp dụng cùng một quy tắc. Tôi biết chính xác lý do tại sao bạn đang làm điều đó, sau đó nó là để làm điều đó. Nhưng đó là trường hợp rất hiếm khi ai đó muốn làm điều gì đó thực sự đặc biệt trong trường hợp của NPE.

8

'Lý do' bắt được NullPointerException được coi là thực hành không tốt không phải vì bạn phải để nó bong bóng khi có sự cố! Nói bất kỳ ngoại lệ nào là 'tốt nhất trái unhandled' chỉ dựa trên loại của nó có vẻ như một ý tưởng tồi.

NPE được coi là kết quả của lỗi lập trình. Một chương trình đúng chính xác không bao giờ nên tạo ra một chương trình. Lý do nhìn thấy nó bị bắt là xấu là nó thường có nghĩa là mã đã ném một, và các lập trình viên quyết định chỉ bắt nó và che đậy nó, thay vì sửa chữa mã bị hỏng gây ra nó ở nơi đầu tiên!

Nếu, ví dụ, bạn đã kết hợp vì lý do kinh doanh với một API có lỗi bên trong và thỉnh thoảng ném một con trỏ rỗng, nó sẽ là hoàn toàn hợp pháp để nắm bắt nó, làm điều gì đó về nó/thông báo cho người dùng thông điệp. Cho phép 'null' nhấn giao diện người dùng chỉ vì một người nào đó nói "Bắt ngoại lệ con trỏ Null là xấu" sẽ không có ý nghĩa!

Bắt java.lang.Exception có thể hợp pháp trong các trường hợp cụ thể, nhưng nói chung "Tôi lười" không phải là một trong số đó. :) Ví dụ nếu bạn đang triển khai một API và muốn chắc chắn rằng không có ngoại lệ nào xuất hiện trong đó, không có trong đặc tả, bạn có thể bắt ngoại lệ và bọc nó trong một số ngoại lệ ứng dụng mà bạn đã định nghĩa.

3

Nói chung, thời gian duy nhất bạn nên bắt một ngoại lệ là nếu bạn có thể xử lý nó theo một cách có ý nghĩa. Nếu bạn không thể, bạn chỉ cần để cho nó bong bóng lên đầu và chấm dứt quá trình. Ví dụ, bạn có thể phục hồi trong một số cách có ý nghĩa từ một lỗi NullPointerException hoặc I/O? Tôi nghĩ là không.

Quy tắc của tôi để xử lý ngoại lệ:

  • Nói chung, không bắt ngoại lệ, trừ khi bạn có thể xử lý chúng trong một số cách có ý nghĩa.
  • Bắt ngoại lệ tại ranh giới quy trình/máy, ghi lại ngoại lệ đã bắt cùng với bất kỳ ngữ cảnh nào có sẵn cho bạn và ném lại. Nếu ngoại lệ là một ngoại lệ tùy chỉnh, bạn có thể bọc nó trong một ngoại lệ của một kiểu đã biết/hữu ích cho quá trình gọi và ném nó.
  • Bạn cũng có thể bắt ngoại lệ ở mức thấp, nơi bạn có ngữ cảnh thời gian chạy nhất có sẵn, đăng nhập ngoại lệ và ngữ cảnh liên quan, sau đó xem lại ngoại lệ.
  • Khi làm lại, hãy sử dụng throw ; thay vì throw caughtException ;. Việc sử dụng cú pháp cũ giữ nguyên dấu vết ngăn xếp ban đầu; sử dụng cú pháp thứ hai tạo ra một dấu vết ngăn xếp mới, bắt đầu bằng throw caughtException ; - bạn mất tất cả ngữ cảnh và ngăn xếp cuộc gọi đến thời điểm ngoại lệ bị bắt.
  • Bạn có thể, nếu bạn chọn, bắt ngoại lệ ở mức cao và chấm dứt hiệu quả quy trình, ghi nhật ký thông tin ngoại lệ để giúp gỡ lỗi và sửa vấn đề cơ bản.

Không sử dụng ngoại lệ làm cơ chế kiểm soát luồng (nếu có thể). Ngoại lệ được cho là, tốt, đặc biệt trong tự nhiên.Thay vào đó, đầu tiên, thực thi kết thúc hợp đồng của người gọi (điều kiện tiên quyết) cho bất kỳ phương thức nào bạn đang gọi.

Xem sách của Bertrand Meyers, Object Oriented Software Construction, 2nd ed. để biết thêm thông tin.

+1

Để trả lời "Khi rethrowing": trong Java bạn không thể "ném", bạn phải "throw caughtException;" và bạn _don't_ mất dấu vết ngăn xếp khi thực hiện nó. – hjhill

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