2010-03-10 28 views

Trả lời

47

Vì khi bạn bắt ngoại lệ , bạn phải xử lý đúng cách. Và bạn không thể mong đợi để xử lý tất cả các loại ngoại lệ trong mã của bạn. Ngoài ra khi bạn bắt tất cả các ngoại lệ, bạn có thể nhận được một ngoại lệ mà không thể xử lý và ngăn chặn mã ở trên trong ngăn xếp để xử lý nó đúng cách.

Hiệu trưởng chung là nắm bắt loại cụ thể nhất mà bạn có thể.

+9

Ví dụ: một java.lang.InterruptedException được nâng lên khi một luồng được yêu cầu dừng lại. Nếu bị bắt và bỏ qua, quá trình xử lý luồng không thể dừng lại một cách duyên dáng và mã của bạn trở nên không đúng để chạy trong một chuỗi công nhân. Đây là một ví dụ, có thể có những người khác. – Pierre

+1

Tôi là một người hâm mộ lớn của những người hiểu khuôn khổ của họ. Lý do chính của lời khuyên này là khủng khiếp, 90% thời gian, mã người đang viết xử lý ngoại lệ, nằm ở ranh giới của API của họ. Tôi đồng ý rằng trong một API, bạn nên luôn luôn nắm bắt các ngoại lệ thích hợp, nhưng khi bạn đang ở một ranh giới API, hãy nắm bắt mọi thứ không giết hệ thống. – coding

5

Vì bạn không thực sự biết tại sao ngoại lệ xảy ra và một số trường hợp ngoại lệ yêu cầu xe rất đặc biệt phải được xử lý chính xác (nếu có thể), chẳng hạn như ngoại lệ OutOfMemoryException và ngoại lệ tương tự ở mức thấp.

Vì vậy, bạn chỉ nên bắt ngoại lệ:

  • mà bạn biết chính xác làm thế nào để đối phó với nó (ví dụ FileNotFoundException hoặc lâu hơn)
  • khi bạn sẽ lại tăng chúng sau đó (ví dụ để thực hiện bài -fail cleanup)
  • khi bạn cần chuyển ngoại lệ sang một chủ đề khác
+0

Không có điều gì như OutOfMemoryException. Có OutOfMemoryError nằm trong hệ thống phân cấp Throwable. –

+2

@EladTabak, bạn hoàn toàn đúng về Java. Điều đó đang được nói, thẻ "java" không có ở đó khi tôi trả lời câu hỏi (xem [lịch sử sửa đổi] (http://stackoverflow.com/posts/2416316/revisions)), và ý nghĩa được truyền đạt là chính xác - bất kể môi trường thực tế. – Lucero

5

Tùy thuộc vào những gì bạn cần. Nếu bạn cần xử lý các loại ngoại lệ khác nhau theo nhiều cách khác nhau thì bạn nên sử dụng nhiều khối catch và nắm bắt được nhiều ngoại lệ cụ thể nhất có thể.

Nhưng đôi khi bạn có thể cần xử lý tất cả các ngoại lệ theo cùng một cách. Trong trường hợp như vậy bắt (Ngoại lệ) có thể là ok. Ví dụ:

try 
    { 
     DoSomething(); 
    } 
    catch (Exception e) 
    { 
     LogError(e); 
     ShowErrorMessage(e); // Show "unexpected error ocurred" error message for user. 
    } 
+2

Đó không phải là một mô hình tốt để làm theo; ghi nhật ký không nên được thực hiện như thế này bởi vì bạn sẽ nhận được một loạt các mục tương tự cho mỗi "cấp" của try-catch. – Lucero

+0

Tôi đồng ý, tôi chỉ sử dụng nó làm ví dụ. Có thể không phải là ví dụ tốt nhất :) –

+1

@Lucero: Tôi nghĩ sẽ tốt hơn nếu có khung đăng nhập có thể hợp nhất các mục thừa, hơn giả định rằng bất kỳ lớp nào xử lý (nuốt) một ngoại lệ sẽ ghi nhật ký. Hơn nữa, trừ khi ngoại lệ rất nhiều khi ghi chúng nhiều lần sẽ đặt ra một nút cổ chai hiệu suất (trong trường hợp này tôi muốn nói * đó là * một vấn đề cần sửa) Tôi sẽ nghĩ có thông tin dư thừa trong nhật ký, sau đó có thể lọc một tiện ích xem nhật ký, sẽ là thích hợp hơn để có một bản ghi ngắn gọn hơn mà thiếu một phần thông tin mà người ta cần. – supercat

8

Bạn chỉ nên bắt ngoại lệ nếu bạn có thể xử lý chúng đúng cách. Vì bạn không thể xử lý đúng tất cả ngoại lệ có thể, bạn không nên bắt chúng :-)

+8

Một vấn đề lớn với suy nghĩ như vậy là có nhiều tình huống trong đó việc xử lý thích hợp cho 99% trường hợp ngoại lệ có thể bị ném sẽ báo cáo rằng một số hành động không thể hoàn thành và tiếp tục với cuộc sống, nhưng xác định mọi loại ngoại lệ mà đó sẽ là hành động thích hợp sẽ rất khó nếu không phải là không thể. Quá xấu không có cơ chế để phân biệt ngoại lệ "không thể đáp ứng yêu cầu" từ ngoại lệ "CPU đang kích hoạt". – supercat

+1

CPU đang cháy có thể sẽ gây ra một số loại 'java.lang.Error'. – yegeniy

+0

> Lỗi là một phân lớp của Throwable cho biết các vấn đề nghiêm trọng mà một ứng dụng hợp lý không nên cố gắng nắm bắt. – yegeniy

15

Câu chuyện ngắn: nó được gọi là đắp mặt nạ lỗi. Nếu bạn có một đoạn mã không hoạt động tốt và loại bỏ các ngoại lệ (hoặc bạn truyền đầu vào không đúng định dạng cho đoạn mã đó) và bạn chỉ mù mắt bằng cách bắt tất cả các ngoại lệ có thể xảy ra, bạn thực sự sẽ không bao giờ phát hiện lỗi và khắc phục lỗi đó.

+0

"Bắt" một ngoại lệ không có nghĩa là chỉ tiếp tục thực hiện như không có gì sai. Một khối "catch" là một khối mã mà bạn làm ** cái gì đó **. Đó ** một cái gì đó **, có thể là để đăng nhập thông tin về ngoại lệ, về những gì người dùng đang làm hoặc trạng thái của giao diện người dùng, để đóng kết nối và các tệp để ứng dụng ca thoát một cách duyên dáng và thông báo cho người dùng điều gì đã xảy ra. Làm thế nào là "che" bất cứ điều gì? – user316117

+0

@ user316117 'Ngoại lệ 'là lớp hàng đầu của tất cả các ngoại lệ trong Java. Bắt được điều đó có nghĩa là bạn bắt được tất cả các lỗi có thể xảy ra. Làm thế nào bạn sẽ biết phải làm gì trong một khối như vậy? Nếu bạn muốn phản ứng với một lỗi nhất định, hãy bắt ngoại lệ cụ thể của nó và làm việc với nó. Không có thực tế sử dụng để bắt tất cả các ngoại lệ có thể ngoại trừ để làm mù mắt của bạn (và tôi đã nhìn thấy rất nhiều đồng nghiệp làm điều đó bởi vì họ muốn về nhà vào cuối ngày làm việc). – dimitarvp

+0

@dimitarvp Throwable là lớp hàng đầu của tất cả các trường hợp ngoại lệ. Nó có hai lớp con phân vùng ngoại lệ trong hai nhánh. Một trong số đó là EXCEPTION và khác là L ERI. –

0

Đây có thể là java cụ thể:

Đôi khi bạn sẽ cần phải gọi các phương thức ném ngoại lệ đã kiểm tra. Nếu điều này nằm trong lớp EJB/business logic của bạn, bạn có 2 lựa chọn - bắt chúng hoặc ném lại chúng.

Bắt các lớp ngoại lệ cụ thể có nghĩa là bạn sẽ cần phải phân tích lại hành động của mình để có thể ném ngoại lệ nào khi bạn xem cách mã này xử lý ngoại lệ. Bạn thường sẽ nhận được vào một "nếu ..." tình hình và nó có thể được rất nhiều nỗ lực chỉ cần làm việc ra nếu trường hợp ngoại lệ được xử lý một cách chính xác.

Tái ném có nghĩa là mã gọi EJB của bạn sẽ được rải rác bằng mã đánh bắt thông thường sẽ không có ý nghĩa gì đối với lớp gọi điện. n.b. ném ngoại lệ đã kiểm tra từ các phương thức EJB sẽ có nghĩa là bạn chịu trách nhiệm tự động quay lại bất kỳ giao dịch nào.

0

Bên cạnh những gì chưa được trả lời bởi @anthares:

Bởi vì khi bạn bắt ngoại lệ bạn đang phải xử lý nó đúng. Và bạn không thể mong đợi để xử lý tất cả các loại ngoại lệ trong mã của bạn. Ngoài ra khi bạn bắt tất cả các ngoại lệ, bạn có thể nhận được một ngoại lệ mà không thể xử lý và ngăn chặn mã ở trên trong ngăn xếp để xử lý nó đúng cách.

Hiệu trưởng chung là nắm bắt loại cụ thể nhất mà bạn có thể.

catch(Exception) là thực tiễn không tốt vì nó cũng nắm bắt tất cả RuntimeException (ngoại lệ không được kiểm soát).

0

Nhưng đôi khi cũng được! Giống như nếu bạn có một đoạn mã làm điều gì đó 'thêm', điều bạn thực sự không quan tâm, và bạn không muốn nó làm nổ tung ứng dụng của bạn. Ví dụ, tôi đã làm việc trên một ứng dụng lớn gần đây, nơi các đối tác kinh doanh của chúng tôi muốn một giao dịch hàng ngày nhất định được tóm tắt trong một tệp nhật ký mới. Họ giải thích rằng nhật ký không quan trọng đối với họ, và nó không đủ tiêu chuẩn như một yêu cầu. Nó chỉ là một cái gì đó thêm mà sẽ giúp họ làm cho tinh thần của dữ liệu được xử lý. Họ không cần nó, bởi vì họ có thể lấy thông tin ở nơi khác. Vì vậy, đó là một trường hợp hiếm hoi mà nó là hoàn toàn tốt để bắt và nuốt ngoại lệ.

Tôi cũng đã làm việc tại một công ty nơi tất cả các Throwables đã bị bắt, và sau đó được sửa lại bên trong một RuntimeException tùy chỉnh. Tôi sẽ không khuyên bạn nên cách tiếp cận này, nhưng chỉ ra rằng nó được thực hiện.

0

Tôi tìm thấy hai sử dụng có thể chấp nhận bắt (Ngoại lệ): - Ở cấp cao nhất của ứng dụng (ngay trước khi trở về người dùng). Bằng cách đó bạn có thể cung cấp một thông điệp đầy đủ. - Sử dụng nó để che giấu ngoại lệ cấp thấp cho một doanh nghiệp.

Trường hợp đầu tiên là tự explanative, nhưng hãy để tôi phát triển thứ hai:

Làm:

try { 
    xxxx 
} catch(Exception e) { 
    logger.error("Error XXX",e) 
} 

là lỗi mặt nạ như @dimitarvp nói.

Nhưng

try { 
    xxxx 
} catch(Exception e) { 
    throw new BussinessException("Error doing operation XXX",e) 
} 

Đó là một điều khác nhau. Bằng cách đó bạn không bỏ qua lỗi và ẩn dưới thảm. Bạn đang cung cấp một ngoại lệ cấp cao với một thông điệp giải thích hơn cho các lớp ứng dụng cao hơn.

Điều quan trọng là cả hai quản lý ngoại lệ ở lớp chính xác của nó. Nếu bạn cho phép leo thang một ngoại lệ cấp thấp lên một tầng kinh doanh cao thì thực tế là lớp cao hơn có thể quản lý nó tốt. Trong trường hợp đó, tôi thích che giấu các ngoại lệ cấp thấp với một doanh nghiệp cung cấp ngữ cảnh và thông điệp tốt hơn và nó cũng có ngoại lệ ban đầu để có thể đi đến chi tiết.

Mặc dù vậy, nếu bạn có thể nắm bắt nhiều ngoại lệ cụ thể hơn và bạn có thể cung cấp điều trị tốt hơn cho họ, bạn phải làm điều đó.

Nếu trong một khối mã, bạn có thể nhận được SQLException và NetworkException, bạn phải nắm bắt chúng và cung cấp đầy đủ các thông điệp và điều trị cho mỗi người trong số họ. Nhưng nếu ở cuối khối try/catch bạn có một ngoại lệ ánh xạ nó với một BussinessException nó ok cho tôi. Trong thực tế, tôi thấy đầy đủ rằng các lớp dịch vụ cao hơn chỉ ném ngoại lệ kinh doanh (với các chi tiết bên trong).

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