Sự khác biệt giữa thử cuối cùng và thử bắt


90

Sự khác biệt giữa

try {
    fooBar();
} finally {
    barFoo();
}

try {
  fooBar();
} catch(Throwable throwable) {
    barFoo(throwable); // Does something with throwable, logs it, or handles it.
}

Tôi thích phiên bản thứ hai hơn vì nó cho tôi quyền truy cập vào Throwable. Có sự khác biệt logic nào hoặc một quy ước ưu tiên nào giữa hai biến thể không?

Ngoài ra, có cách nào để truy cập ngoại lệ từ mệnh đề cuối cùng không?

Câu trả lời:


121

Đây là hai điều khác nhau:

  • Khối catch chỉ được thực thi nếu một ngoại lệ được ném vào khối try.
  • Khối cuối cùng được thực thi luôn sau khối try (-catch), nếu một ngoại lệ được ném ra hoặc không.

Trong ví dụ của bạn, bạn đã không hiển thị cấu trúc khả thi thứ ba:

try {
    // try to execute this statements...
}
catch( SpecificException e ) {
    // if a specific exception was thrown, handle it here
}
// ... more catches for specific exceptions can come here
catch( Exception e ) {
    // if a more general exception was thrown, handle it here
}
finally {
    // here you can clean things up afterwards
}

Và, như @codeca nói trong bình luận của mình, không có cách nào để truy cập ngoại lệ bên trong khối cuối cùng, bởi vì khối cuối cùng được thực thi ngay cả khi không có ngoại lệ.

Tất nhiên bạn có thể khai báo một biến chứa ngoại lệ bên ngoài khối của bạn và gán một giá trị bên trong khối bắt. Sau đó, bạn có thể truy cập biến này bên trong khối cuối cùng của mình.

Throwable throwable = null;
try {
    // do some stuff
}
catch( Throwable e ) {
    throwable = e;
}
finally {
    if( throwable != null ) {
        // handle it
    }
}

11
Một hệ quả tất yếu đó là bạn không thể truy cập Throwabletừ các finallykhối, vì có thể không một Throwable.
Dean Harding

11

Đây không phải là những biến thể, về cơ bản chúng là những thứ khác nhau. luônfinally được thực thi , chỉ khi một ngoại lệ xảy ra.catch


7

Các khối cuối cùng và bắt khá khác nhau:

  • Trong khối bắt bạn có thể phản hồi với ngoại lệ đã ném. Khối này chỉ được thực thi nếu có một ngoại lệ chưa được xử lý và kiểu khớp với một hoặc là lớp con của lớp được chỉ định trong tham số của khối bắt.
  • Cuối cùng sẽ luôn được thực thi sau khi thử và bắt các khối cho dù có ngoại lệ được nêu ra hay không.

Vì thế

try {
  //some code
}
catch (ExceptionA) {
  // Only gets executed if ExceptionA 
  // was thrown in try block
}
catch (ExceptionB) {
  // Only executed if ExceptionB was thrown in try 
  // and not handled by first catch block
}

khác với

try {
  //some code
}
finally {
  // Gets executed whether or not 
  // an exception was thrown in try block
}

đáng kể.

Nếu bạn xác định một khối thử, bạn phải xác định

  1. một khối cuối cùng, hoặc
  2. một hoặc nhiều khối bắt, hoặc
  3. một hoặc nhiều khối bắt và một khối cuối cùng

Vì vậy, mã sau đây cũng sẽ hợp lệ:

try {
  //some code
}
catch (ExceptionA) {
  // Only gets executed if 
  // ExceptionA was thrown in try block
}
catch (ExceptionB) {
  // Only executed if ExceptionB was thrown in 
  // try and not handled by first catch block
}
//even more catch blocks
finally {
  // Gets executed whether or not an 
  // exception was thrown in try block
}

4

try được sử dụng để chạy một phương thức có thể tạo ra một ngoại lệ

catch được sử dụng để "bắt" dừng ngoại lệ đó

finally được sử dụng cho bất kỳ quá trình dọn dẹp nào cần thiết từ việc ngoại lệ đó có bị bắt hay không

try{
    myObject.riskyMethod(); // run a method that may throw an exception
}
catch(Exception ex){
    myLogger.log(ex.Message); // "catch" stop that exception
}
finally{
    myObject = null; // clean up needed from that exception being caught
}

3
try {
    statements;
} catch (exceptionType1 e1) {      // one or multiple
    statements;                 
} catch (exceptionType2 e2) {
    statements;
}    
...
} finally {                                 // one or none
    statements;
}
  1. Tất cả các câu lệnh try phải bao gồm một mệnh đề bắt hoặc mệnh đề cuối cùng
  2. Nó có thể có nhiều mệnh đề bắt nhưng chỉ có một mệnh đề cuối cùng
  3. Trong quá trình thực thi, nếu có lỗi xảy ra, thì Control được chuyển đến khối Catch thích hợp và thực hiện các câu lệnh và khối Cuối cùng được thực thi.

Không có vấn đề gì Khối Cuối cùng luôn được thực thi, Vì vậy, nói chung, khối Cuối cùng được sử dụng, khi bạn có phiên, kết nối Cơ sở dữ liệu hoặc Tệp hoặc ổ cắm đang mở, thì mã đóng các kết nối đó sẽ được đặt. Điều này chỉ để đảm bảo ứng dụng không bị rò rỉ bộ nhớ hoặc Không xảy ra bất kỳ sự cố nào khác.


3

Các khối cuối cùng và bắt khá khác nhau:

Trong khối bắt bạn có thể phản hồi với ngoại lệ đã ném. Khối này chỉ được thực thi nếu có một ngoại lệ chưa được xử lý và kiểu khớp với một hoặc là lớp con của lớp được chỉ định trong tham số của khối bắt. Cuối cùng sẽ luôn được thực thi sau khi thử và bắt các khối cho dù có ngoại lệ được nêu ra hay không.


2

Trong Tìm kiếm lại của tôi Khối cuối cùng luôn được thực thi và nó chủ yếu được "sử dụng để đóng bất kỳ kết nối mở nào" và để phá hủy thứ gì đó đang chạy không cần thiết.


2

Nói chung, khi chúng tôi sử dụng bất kỳ tài nguyên nào như luồng, kết nối, v.v., chúng tôi phải đóng chúng một cách rõ ràng bằng cách sử dụng khối cuối cùng. Trong chương trình dưới đây, chúng tôi đang đọc dữ liệu từ một tệp bằng FileReader và chúng tôi đang đóng nó bằng cách sử dụng khối cuối cùng.

import java.io.File;
import java.io.FileReader;
import java.io.IOException;

public class ReadData_Demo {

   public static void main(String args[]){
      FileReader fr=null;       
      try{
         File file=new File("file.txt");
         fr = new FileReader(file);  char [] a = new char[50];
         fr.read(a); // reads the content to the array
         for(char c : a)
         System.out.print(c); //prints the characters one by one
      }catch(IOException e){
          e.printStackTrace();
       }
       finally{ 
          try{
              fr.close();
          }catch(IOException ex){       
               ex.printStackTrace();
           }
       }
    }

}

Có lẽ những người khác như tôi đã tìm kiếm một cái gì đó như thế này.

Thông tin từ trang này tutpoint


1

Cuối cùng khối luôn được thực thi. Khối bắt chỉ được thực thi khi một ngoại lệ khớp với tham số khối được bắt.


1

Ngay cả trong biểu mẫu đầu tiên, bạn có thể đăng nhập nó trong phương thức gọi. Vì vậy, không có lợi thế lớn trừ khi bạn muốn thực hiện một số xử lý đặc biệt ngay tại đó.


0

Khối try sẽ giữ các câu lệnh sẽ tăng ngoại lệ. Khối catch sẽ giữ tham chiếu được ném ra từ khối try và các thông báo bắt buộc được tạo từ khối catch. Cuối cùng, khối cũng được sử dụng để đóng các tài nguyên đã sử dụng như đóng io, đóng tệp, đóng dB .. Trong Java -9 nâng cao try-with resource đã xuất hiện nơi các tài nguyên được khai báo bên ngoài try..trong thử với resource, khối catch là bắt buộc

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.