2009-01-31 8 views
37

Given: Throwable là superclass của Exception.Khi nào nên sử dụng Throwable thay vì ngoại lệ mới?

Khi tôi đọc văn bản để viết 'ngoại lệ' của riêng mình, tôi thấy ví dụ về Throwable đang được sử dụng trong khối catch và các văn bản khác hiển thị new Exception() đang được sử dụng trong khối catch. Tôi vẫn chưa thấy một lời giải thích khi nào thì nên sử dụng.

Câu hỏi của tôi là, khi nào nên sử dụng Throwable và khi nào nên sử dụng new Exception()?

EDIT: Bên trong catch hoặc else khối bằng cách sử dụng:

throw throwable; 

hoặc

throw new Exception(); 
+1

Tại sao bạn sử dụng "mới"? Bạn có so sánh bắt (Throwable) vs bắt (ngoại lệ)? –

+0

@WolfmanDragon: Vì vậy, bạn đang ném Throwable/Exception từ * bên trong * khối catch? Chúng ta có giả định rằng "có thể ném" là một Throwable có thể bị chặn bởi khối đó không? –

+0

@Zach Scrivena: không, đây là câu hỏi chung. Tôi đã viết ngoại lệ trong C + + nhưng không bao giờ trong Java, và tôi là một chút bối rối. Vấn đề đưa ra điều này là tôi cần phải chuyển một 'ngoại lệ' cho một đoạn mã mà một đồng nghiệp đang xây dựng nếu một bộ sưu tập không được xây dựng. – WolfmanDragon

Trả lời

11

(từ bình luận) Vấn đề mà đem này lên là tôi cần phải vượt qua một 'ngoại lệ' để một mảnh mã một đồng nghiệp đang xây dựng nếu một bộ sưu tập không được xây dựng.

Trong trường hợp đó, bạn có thể muốn ném ngoại lệ đã kiểm tra. Bạn có thể ném Exception, một lớp con hiện có thích hợp của nó (ngoại trừ RuntimeException và các lớp con của nó là không được chọn) hoặc lớp con tùy chỉnh của Exception (ví dụ: "CollectionBuildException"). Xem Java Tutorial on Exceptions để tăng tốc với ngoại lệ Java.

+0

Trong khi câu trả lời của bạn trả lời bình luận của tôi, tôi vẫn không hiểu tại sao một số tên tuổi lớn trong lĩnh vực nói ném Throwable (Hardcore Java bởi Robert Simmons, Jr.) trong khi những người khác nói không bao giờ sử dụng Throwable. Hardcore Java xảy ra là cuốn sách java bao giờ hết, ngoại trừ trong trường hợp này. – WolfmanDragon

+3

Có thể ném được là siêu lớp của Ngoại lệ và Lỗi. Trong ba lớp học, tôi sẽ xem Ngoại lệ là một trong những phù hợp nhất cho nhiệm vụ. Hầu hết mọi người viết các khối try-catch chỉ nhìn ra ngoại lệ và các lớp con của nó; họ sẽ không thể xử lý một Throwable mới(). –

+0

(tiếp) trừ khi có một "bắt (Throwable t)" quá. –

32

Luôn ném một ngoại lệ (không bao giờ một Throwable). Bạn thường không bắt được Throwable, nhưng bạn có thể. Throwable là superclass cho Exception và Error, vì vậy bạn sẽ bắt được Throwable nếu bạn không muốn bắt ngoại lệ mà còn là lỗi, đó là điểm có nó. Vấn đề là, lỗi thường là những thứ mà một ứng dụng bình thường sẽ không và không nên bắt, vì vậy chỉ cần sử dụng ngoại lệ trừ khi bạn có một lý do cụ thể để sử dụng Throwable.

+6

Không ném ngoại lệ, ném lớp phụ Ngoại lệ thích hợp hoặc của riêng bạn. Toàn bộ điểm ngoại lệ có các lớp con là các loại vấn đề khác nhau có thể có ngoại lệ riêng của chúng. Ngoài việc bao gồm thông điệp và có thể bao gồm nguyên nhân ngoại lệ, người ta có thể thêm "dữ liệu" bổ sung. –

+0

Vâng, đó là ý của tôi, hãy ném một lớp con của Ngoại lệ. Xin lỗi đã không suy nghĩ đủ cứng. –

+1

đây là câu trả lời đúng. người hỏi đã thực hiện một sự lựa chọn không may cho người nào đánh dấu đúng. cũng xem nhận xét của cHao về một câu trả lời khác ở trên, bổ sung cho câu trả lời này một cách độc đáo. – necromancer

1

Có thể ném là giao diện chứ không phải lớp học. Hai lớp mở rộng Throwable, Exception and Error.

Quy tắc là: cụ thể như bạn có thể khi bắt ngoại lệ - điều đó có nghĩa là ví dụ bắt ngoại lệ thay vì Throwable và IOException thay vì Ngoại lệ.

Không bắt lỗi - lỗi là lỗi. Sửa mã thay thế.

Nếu bạn phải nắm bắt hoàn toàn mọi thứ, hãy sử dụng "catch Throwable", nhưng đây là hình thức xấu.

+0

Throwable là một lớp bê tông quá. –

+0

Này, thực ra tôi đã bị ấn tượng bởi Throwable là một giao diện cho đến khi tôi nhìn. Không chắc chắn tại sao điều này là hoặc nếu đây là một điều mới. –

+0

Cảm ơn bạn đã chỉ ra điều đó - tôi đoán tôi đã bị lừa bởi hậu tố có thể. –

7

Bạn không nên bắt ngoại lệ và ném một ngoại lệ mới chung chung là "ngoại lệ mới".

Thay vào đó, nếu bạn muốn bong bóng lên ngoại trừ chỉ làm như sau:

try { 
    // Do some stuff here 
} 
catch (DivideByZeroException e) { 
    System.out.println("Can't divide by Zero!"); 
} 
catch (IndexOutOfRangeException e) { 
    // catch the exception 
    System.out.println("No matching element found."); 
} 
catch (Throwable e) { 
    throw e; // rethrow the exception/error that occurred 
} 

Nó không phải là thói quen tốt, tôi tin rằng, để bắt một ngoại lệ và ném một ngoại lệ mới thay vì một trong đó là được nâng lên khối mã của bạn, trừ khi bạn đưa ra một ngoại lệ tùy chỉnh hữu ích cung cấp đủ ngữ cảnh để tránh né nguyên nhân của ngoại lệ ban đầu.

+0

Mã của bạn không phải là Java. – starblue

+2

Mã này sẽ loại bỏ các ngoại lệ DivideByZero và IndexOutOfRange. Đăng nhập ngoại lệ trước khi ném nó thường là một ý tưởng tồi. Nếu một ngoại lệ được ghi lại ở tất cả, nó thường là tốt nhất để làm điều đó ở cấp độ trong ngăn xếp có trách nhiệm thực sự xử lý lỗi, mà không tái ném. – erickson

+2

Mã này nhằm giải quyết câu hỏi của người hỏi. Các phương pháp hay nhất không ảnh hưởng đến câu hỏi của người hỏi nằm ngoài phạm vi của câu trả lời này. Tôi chỉ muốn cho thấy rằng bạn có thể giải quyết các trường hợp ngoại lệ nhưng vẫn rethrow ngoại lệ nếu một ngoại lệ đặc biệt đã xảy ra. – MichaelD

0

Như tôi đã nghe khi java xuất hiện lần đầu tiên, lý thuyết là Throwable có thể được sử dụng để chuyển quyền kiểm soát trong các trường hợp khác ngoài ngoại lệ. Tôi chưa bao giờ thấy nó được sử dụng theo cách đó mặc dù (và đó có thể là một điều rất tốt).

Vì vậy, chỉ cần nắm bắt Ngoại lệ (hoặc tốt hơn, một ngoại lệ chi tiết hơn).

0

Có thể ném được để chỉ bị bắt bởi vùng chứa hoặc vòng lặp chính của chương trình của bạn. Hầu hết thời gian bắt nội dung bên dưới Ngoại lệ ví dụ: Lỗi không thêm nhiều khả năng vào một chương trình, sau tất cả những gì bạn có thể làm nếu một lỗi VirtualError khác được ném. Không nhiều ngoại trừ việc đăng nhập và tiếp tục.

+0

Vì vậy, sử dụng throwable nếu nó được chuyển đến chính hoặc servlet để đưa ra quyết định logic? ngoại lệ mới() nếu nó chỉ là để được đăng nhập? – WolfmanDragon

1

throw new Exception(); là điều bạn nên bao giờ làm trong một khối catch, nhưng bạn có thể phải hoặc muốn làm ném new SomeException(throwable); (bảo quản stack trace đầy đủ) thay vì throw throwable; để phù hợp với các API của phương pháp của bạn, ví dụ khi nó tuyên bố ném SomeException nhưng bạn đang gọi mã có thể ném một số IOException mà bạn không muốn thêm vào mệnh đề throws của phương thức của bạn.

Trường hợp phổ biến nhất có thể là new RuntimeException(throwable); để tránh hoàn toàn một mệnh đề throws. Nhiều người sẽ cho bạn biết đây là một sự lạm dụng khủng khiếp bởi vì bạn nên sử dụng các ngoại lệ đã kiểm tra. IMO họ là sai và kiểm tra ngoại lệ là một sai lầm trong thiết kế ngôn ngữ Java mà chỉ kết quả trong xấu xí, mã unmaintainable.

+1

Ngoại lệ không được kiểm soát là nguyên nhân phổ biến của "trừu tượng bị rò rỉ". http://www.joelonsoftware.com/articles/LeakyAbstractions.html Chúng phù hợp với báo cáo lỗi một kích thước phù hợp - hữu ích trong nhiều trường hợp - nhưng chúng không thể hỗ trợ xử lý ngoại lệ thực sự khi đối mặt với sự trừu tượng hóa . – erickson

0

Tất cả ngoại lệ đều là vấn đề cuối cùng ... quá nói Lỗi là lỗi không có nghĩa gì cả.

Lỗi không phải là lỗi - chúng là vấn đề mà máy chủ lưu trữ đang gặp phải, ví dụ như OutOfMemoryError. Ngoại lệ là một phương tiện mà hoạt động hiện tại có thể sử dụng để thông báo rằng nó không thành công và có thể cung cấp một số chẩn đoán.

0

Nói chung, bạn sẽ không ném hoặc bắt Được ném. Cụ thể, lỗi JVM (mở rộng Lỗi()) không phải là có nghĩa là bị mã người dùng bắt, trừ khi bạn đang làm việc ở mức hệ thống kỳ lạ.

Xử lý "Có thể ném" dưới dạng ngôn ngữ tạo tác. Lớp "Ngoại lệ" được đặt tên bởi vì nó là một trong đó là dự định được sử dụng bởi các lập trình viên khi họ muốn một khối mã để thoát "đặc biệt" - bằng cách không thoát bình thường hoặc trả về một giá trị.

Điều đó bao gồm cả các tình huống lỗi thông thường (theo "thông thường", có nghĩa là trái ngược với lỗi JVM) và những nơi bạn đang sử dụng ngoại lệ làm cơ chế điều khiển.

0

Bạn không nên sử dụng ngoại lệ như là một "kiểu trả về" một trong hai ...

Nếu điều kiện bạn đang ném cho là phổ biến, bạn phải bỏ ra một số tiền rất lớn của nguồn lực để quay trở lại tình trạng đó để kêu gọi công Việt Hằng ngày. Trường hợp ngoại lệ là tốn kém để xây dựng.

Tôi đã nhìn thấy các trường hợp các vòng chặt chẽ đã ném ngoại lệ là "tiêu cực" cho ví dụ: Phân bổ ID, thói quen này chiếm khoảng 99% thời gian của CPU .. khi thay đổi thành hằng số trả về được ghi lại, điều này giảm xuống còn 25%.

5

Chỉ hai nơi bạn sẽ thấy từ Throwable trong mã:

public static void main(String args[]) 
{ 
    try 
    { 
     // Do some stuff 
    } 
    catch(Throwable t) 
    { 

    } 
} 

public class SomeServlet extends HttpServlet 
{ 
     public void doPost(HttpRequest request, HttpResponse response) 
     { 
     try 
     { 
      // Do some stuff 
     } 
     catch (Throwable t) 
     { 
       // Log 
     } 
     } 
} 
+5

Ngay cả hai số này sẽ có ít nhất một quá nhiều IMO. Bắt 'Throwable' (đặc biệt là bên ngoài của 'main') là một công thức cho thảm họa, khi bạn đang đúc cách quá rộng một mạng. Không chỉ là ngoại lệ ở cấp ứng dụng là Throwable. Ví dụ phổ biến: Lỗi OOM. Làm thế nào bạn sẽ đăng nhập chúng, nếu hành động của việc viết một bản ghi gây ra một đối tượng được tạo ra (đọc: được phân bổ, bởi chính quá trình vừa thất bại)? Và khi đó * không * thất bại, những gì bây giờ? Bạn đã mất thông tin gây ra lỗi ban đầu, vì bạn đã gây ra lỗi mới sẽ được truyền bá thay thế. Đó là nếu ứng dụng không chỉ chết. – cHao