Java Thử Catch Cuối cùng các khối mà không Bắt


125

Tôi đang xem xét một số mã mới. Chương trình có một thử và cuối cùng chỉ chặn. Vì khối bắt được loại trừ, khối thử hoạt động như thế nào nếu nó gặp ngoại lệ hoặc bất cứ thứ gì có thể ném được? Nó chỉ đi trực tiếp đến khối cuối cùng?



25
@mP Mọi người nên thực hiện đánh giá mã và đặt câu hỏi từ họ là cách học và cải thiện.
Carl Pritchett

Câu trả lời:


130

Nếu bất kỳ mã nào trong khối thử có thể đưa ra một ngoại lệ được kiểm tra, thì nó phải xuất hiện trong mệnh đề ném của chữ ký phương thức. Nếu một ngoại lệ không được kiểm tra được ném ra, nó sẽ bị bong ra khỏi phương thức.

Khối cuối cùng luôn được thực thi, cho dù có ngoại lệ được ném hay không.


11
Đoạn đầu tiên không nhất thiết là đúng. Thử khối có thể được lồng nhau. Bất kỳ ngoại lệ chưa được kiểm tra, không được kiểm tra hoặc không, sẽ bong bóng ra khỏi phương thức.
Andy Thomas

4
Các khối thử có thể được lồng nhau, nhưng tôi không khuyên bạn nên dùng nó. Tôi không viết mã theo cách đó.
duffymo

2
@duffymo: Ý nghĩa của "bong bóng ra khỏi phương pháp" là gì?
Hôm nay học

5
@Anand chỉ là một số ngôn ngữ hơi phi kỹ thuật để "ném một ngoại lệ".
duffymo

2
Không bỏ qua; vượt qua chuỗi phương pháp.
duffymo

93

Một lưu ý nhỏ trên try/ finally: Cuối cùng sẽ luôn luôn thực thi trừ khi

  • System.exit() được gọi là.
  • JVM gặp sự cố.
  • Các try{}khối không bao giờ kết thúc (ví dụ như vô tận vòng lặp).

4
Thế còn try{..} catch{ throw ..} finally{..}? Tôi nghĩ cuối cùng sẽ không bị xử tử
sbeliakov

10
Trong trường hợp đó cuối cùng vẫn sẽ được gọi. Chỉ có ngoại lệ ban đầu bị mất.
Peter Lawrey

Cuối cùng cũng sẽ không được thực thi nếu bạn gọi System.exit () trước đó.
mmirror

2
@jyw Đó là ý của mục đầu tiên trong danh sách trên.
Peter Lawrey

Tôi phải nói rằng, điều này bao gồm tất cả các cơ sở!
Oscar Bravo

39

Đặc tả ngôn ngữ Java (1) mô tả cách try-catch-finallythực thi. Không bắt được tương đương với việc không bắt được có thể bắt được Ném được.

  • Nếu việc thực thi khối thử hoàn thành đột ngột vì ném giá trị V, thì có một lựa chọn:
    • Nếu loại thời gian chạy của V có thể gán cho tham số của bất kỳ mệnh đề bắt nào của câu lệnh thử, thì
      ...
    • Nếu loại thời gian chạy của V không thể gán cho tham số của bất kỳ mệnh đề bắt nào của câu lệnh thử, thì khối cuối cùng được thực thi . Sau đó, có một sự lựa chọn:
      • Nếu khối cuối cùng hoàn thành bình thường, thì câu lệnh thử hoàn thành đột ngột vì ném giá trị V.
      • Nếu khối cuối cùng hoàn thành đột ngột vì lý do S, thì câu lệnh thử hoàn thành đột ngột vì lý do S (và việc ném giá trị V bị loại bỏ và bị lãng quên).

(1) Thi hành thử bắt cuối cùng


16

Phần bên trong cuối cùng được thực thi trước khi ném ngoại lệ vào khối bên ngoài.

public class TryCatchFinally {

  public static void main(String[] args) throws Exception {

    try{
        System.out.println('A');
        try{
            System.out.println('B');
            throw new Exception("threw exception in B");
        }
        finally
        {
            System.out.println('X');
        }
        //any code here in the first try block 
        //is unreachable if an exception occurs in the second try block
    }
    catch(Exception e)
    {
        System.out.println('Y');
    }
    finally
    {
        System.out.println('Z');
    }
  }
}

Kết quả trong

A
B
X
Y
Z

6

Khối cuối cùng luôn được chạy sau khi khối thử kết thúc, cho dù thử kết thúc bình thường hay bất thường do ngoại lệ, er, có thể ném được.

Nếu một ngoại lệ được ném bởi bất kỳ mã nào trong khối thử, thì phương thức hiện tại chỉ cần ném lại (hoặc tiếp tục ném) cùng một ngoại lệ (sau khi chạy khối cuối cùng).

Nếu khối cuối cùng ném ra một ngoại lệ / lỗi / có thể ném được, và đã có một lần ném đang chờ xử lý, nó sẽ trở nên xấu xí. Thẳng thắn mà nói, tôi quên chính xác những gì xảy ra (rất nhiều cho chứng nhận của tôi nhiều năm trước). Tôi nghĩ cả hai ném đều được liên kết với nhau, nhưng có một số voodoo đặc biệt bạn phải làm (nghĩa là - một cuộc gọi phương thức tôi sẽ phải tìm kiếm) để có được vấn đề ban đầu trước khi "cuối cùng" bị chặn, er, ném lên.

Ngẫu nhiên, thử / cuối cùng là một điều khá phổ biến để quản lý tài nguyên, vì java không có hàm hủy.

Ví dụ -

r = new LeakyThing();
try { useResource( r); }
finally { r.release(); }  // close, destroy, etc

"Cuối cùng", một tip hơn: nếu bạn làm bận tâm để đưa vào một nắm bắt, hoặc là bắt cụ thể (dự kiến) lớp con Throwable, hoặc chỉ bắt "Throwable", không "ngoại lệ", cho một nhận tất cả bẫy lỗi chung. Quá nhiều vấn đề, chẳng hạn như sự phản xạ, ném "Lỗi", thay vì "Ngoại lệ" và những vấn đề đó sẽ xảy ra ngay lập tức bởi bất kỳ "bắt tất cả" nào được mã hóa như sau:

catch ( Exception e) ...  // doesn't really catch *all*, eh?

làm điều này thay vào đó:

catch ( Throwable t) ...

Xem câu trả lời của Carlos Heuberger dưới đây cho phần xấu xí.
mplwork

3

Các phiên bản Java trước phiên bản 7 cho phép ba kết hợp thử-bắt-cuối ...

try - catch
try - catch - finally
try - finally

finallykhối sẽ luôn được thực thi bất kể điều gì đang xảy ra trong khối try/ và catch. vì vậy nếu không có catchkhối, ngoại lệ sẽ không được xử lý ở đây.

Tuy nhiên, bạn vẫn sẽ cần một trình xử lý ngoại lệ ở đâu đó trong mã của bạn - trừ khi bạn muốn ứng dụng của mình bị sập hoàn toàn. Nó phụ thuộc vào kiến ​​trúc của ứng dụng của bạn chính xác nơi xử lý đó.

  • Khối thử Java phải được theo sau bởi khối bắt hoặc cuối cùng.
  • Đối với mỗi khối thử có thể có 0 hoặc nhiều khối bắt, nhưng chỉ có một khối cuối cùng.
  • Khối cuối cùng sẽ không được thực thi nếu chương trình thoát (bằng cách gọi System.exit () hoặc bằng cách gây ra lỗi nghiêm trọng khiến quá trình hủy bỏ).

1
"Trước khi phiên bản 7 cho phép" bạn có ngụ ý rằng Java 7 và Java 8 không cho phép ba kết hợp này không? Tôi nghi ngờ đó là những gì bạn muốn nói, nhưng đó là những gì câu trả lời của bạn ngụ ý.
Loduwijk

khối cuối cùng được thực thi nếu có câu lệnh return trong khối try?
Rahul Yadav

@Rahul Vâng, cuối cùng sẽ được gọi. Tham chiếu: stackoverflow.com/questions/65035/ từ
roottraveller

1
@Aaron - cú pháp mới cho try-with-resource tự động gọi .close () trên bất kỳ thứ gì được xây dựng trong parens chỉ sau từ khóa try.
Roboprog

2

khối thử hoạt động như thế nào nếu nó gặp ngoại lệ hoặc bất cứ thứ gì có thể ném được

Ngoại lệ được ném ra khỏi khối, giống như trong mọi trường hợp khác mà nó không bị bắt.

Khối cuối cùng được thực thi bất kể khối thoát được thoát ra như thế nào - bất kể có bắt được gì hay không, bất kể có bắt được khớp hay không.

Các khối bắt và cuối cùng là các phần trực giao của khối thử. Bạn có thể có một hoặc cả hai. Với Java 7, bạn sẽ không thể có!


1

Bạn không thử nó với chương trình đó à? Cuối cùng, nó sẽ chặn và thực hiện khối cuối cùng, nhưng, ngoại lệ sẽ không được xử lý. Nhưng, ngoại lệ đó có thể được ghi đè trong khối cuối cùng!


1

Khối cuối cùng được thực thi sau khi khối thử hoàn thành. Nếu một cái gì đó được ném vào bên trong khối thử khi nó rời khỏi khối cuối cùng được thực thi.


0

Bên trong trykhối chúng tôi viết mã có thể ném một ngoại lệ. Các catchkhối là nơi chúng ta xử lý các ngoại lệ. Cácfinally khối luôn thực hiện bất kể ngoại lệ xảy ra hay không.

Bây giờ nếu chúng ta có khối thử cuối cùng thay vì khối thử-bắt-cuối thì ngoại lệ sẽ không được xử lý và sau khối thử thay vì điều khiển sẽ bắt khối thì cuối cùng sẽ chặn. Chúng ta có thể sử dụng khối thử cuối cùng khi chúng ta không muốn làm gì với ngoại lệ.


0

Bất kể ngoại lệ được ném hay không trong trykhối - finallykhối sẽ được thực thi. Ngoại lệ sẽ không bị bắt.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.