2013-03-21 19 views
5

Giả sử rằng đoạn mã này là trong 20 nơi và luôn luôn giống nhauCatch ngoại lệ riêng biệt hoặc sử dụng instanceof - Java 6

try { 
    // do something 
} catch (FirstException e) { 
    // log it 
} catch (SecondException e) { 
    // log it 
} 

sẽ không thể tốt hơn để sử dụng một cái gì đó như thế này hay instanceof không phải là giải pháp tốt?

try { 
    // do something 
} catch(Exception e) { 
    logException(e); 
} 

void logException(Exception e) { 
    if (e instanceof FirstException) { 
     // log it 
    } else if (e instanceof SecondException) { 
     // log it differently 
    } else { 
     // do something with other exception 
    } 
} 

Điều duy nhất mà tôi thực sự ghét về giải pháp là bắt Exception đó là definitelly không phải là cách tốt nhất ... Có cách nào tốt hơn?

+0

Tôi muốn sử dụng cách tiếp cận đầu tiên và gọi logException cho tất cả các ngoại lệ bị bắt. – Thihara

+0

Điều gì sẽ xảy ra nếu 'FileNotFoundException' bị ném !!! – Azodious

+0

Nắm bắt từng ngoại lệ riêng biệt chỉ có ý nghĩa khi bạn định thực hiện xử lý khác nhau cho mỗi trường hợp. Trong các ứng dụng thực tế, điều này hiếm khi xảy ra. Cách tiếp cận khả thi là bắt tất cả bằng cách sử dụng superclass 'Exception' hoặc 'Throwable' nếu lỗi thời gian chạy là mối quan tâm chính và ** đăng nhập ** chúng một cách chính xác để có ý nghĩa với nhà phát triển ở đâu và những gì thực sự xảy ra. – Vrushank

Trả lời

8
  1. Trong Java 7, sử dụng catch (FirstException1 | SecondException | ...)
  2. Có thể có gì sai với catch (Exception e) — bạn muốn đăng nhập tất cả trường hợp ngoại lệ, không bạn? Tôi thực sự sẽ tư vấn cho catch (Throwable t)OutOfMemoryError s và StackOverflowError cũng muốn được ghi nhật ký.

Lời khuyên từ nhiều năm kinh nghiệm với ngoại lệ ghi nhật ký là ghi lại tất cả cùng một cách. Thông báo ngoại lệ là đủ như văn bản có thể đọc được của con người và những gì nhà phát triển thực sự cần để gỡ lỗi là theo dõi ngăn xếp. Chỉ cần cẩn thận về một điều: không bao giờ bắt ngoại lệ quá sớm: bắt chúng ở một nơi duy nhất cho toàn bộ ứng dụng, cái gọi là rào cản ngoại lệ — nó ở cấp độ bạn nhập và thoát khỏi một đơn vị công việc.

Nếu trường hợp ngoại lệ kiểm tra đang đưa bạn gặp rắc rối ở cấp thấp hơn, quấn chúng vào RuntimeException:

try { 
    ... 
} 
catch (RuntimeException e) {throw e;} 
catch (Exception e) {throw new RuntimeException(e);} 

Chỉ nếu bạn biết một cách chính xác và trước đó có một ngoại lệ trong đó có ý nghĩa kinh doanh cấp để ứng dụng của bạn và sẽ không phải hủy bỏ đơn vị công việc hiện tại, nhưng chuyển hướng luồng công việc của nó, có phù hợp để bắt ngoại lệ đó ở cấp thấp hơn không. Trong thực tế ngoại lệ như vậy là rất hiếm so với tổng thể của tất cả các trường hợp ngoại lệ có thể được ném bởi mã ứng dụng.

+2

Không bắt được Có thể ném được như ác quỷ lớn nhất của tất cả? Bởi vì tôi không muốn bắt tất cả các trường hợp ngoại lệ ... chỉ cần hai số – user219882

+0

Chỉ khi bạn bắt chúng quá sớm --- như tôi giải thích trong câu trả lời đã chỉnh sửa. –

+0

Cảm ơn - không biết bạn có thể bắt ngoại lệ | b trong java 7 (chủ yếu là làm việc trong Obj-C gần đây). . . mẹo tiện dụng. –

1

Cách tiếp cận đầu tiên chắc chắn là tốt hơn. Nói chung, thực tiễn không tốt là bắt được Exception vì trong trường hợp này bạn cũng bắt được RuntimeException.

1

Trước đây là giải pháp sạch sẽ và tuyệt vời nếu bạn chỉ phải đăng nhập ngoại lệ.

Cách tiếp cận đầu tiên khác tốt hơn.

1

Trong cuốn sách "Tái cấu trúc thành mẫu" một trong các phép tái cấu trúc phổ biến là "thay thế instanceof bằng đa hình" - nói cách khác bất cứ khi nào bạn sử dụng instanceof, xem xét liệu polymporphism có thực sự hoạt động tốt hơn không. . .

Có nói rằng, đối với câu hỏi cụ thể này, triết lý mùa xuân thay thế các ngoại lệ đã kiểm tra với các ngoại lệ thời gian chạy lò xo đến tâm trí (lý do chơi chữ).

Ý tưởng là ngoại lệ đã kiểm tra có thể bị lạm dụng - là ngoại lệ có thể khôi phục được không? Nếu có, ok. . . nếu không, hãy để nó lan truyền chuỗi.Bạn có thể thực hiện điều này bằng cách:

  • Phát lại. . . (Nhưng vẫn tốt hơn)
  • Wrap nó trong một RuntimeException

Tạo một Aspect logging:

Một điều cần xem xét ở đây là nếu bạn cần phải đăng nhập những ngoại lệ này ở chính xác điểm chúng xảy ra thay vì để họ tuyên truyền chuỗi, rằng chúng xuất hiện ở 20 địa điểm khác nhau, thì chúng là mối quan tâm chéo. . . Bạn có thể có các phương pháp thường xuyên chỉ cần rethrow ngoại lệ, và sau đó viết một khía cạnh để bắt và đăng nhập chúng. . . . một lần nữa bằng cách sử dụng Spring làm cho điều này dễ dàng.