Java try-with-resource

Trong hướng dẫn này, chúng ta sẽ tìm hiểu về câu lệnh try-with-resources để tự động đóng tài nguyên.

Câu try-with-resourceslệnh tự động đóng tất cả các tài nguyên ở cuối câu lệnh. Tài nguyên là một đối tượng được đóng ở cuối chương trình.

Cú pháp của nó là:

try (resource declaration) {
  // use of the resource
} catch (ExceptionType e1) {
  // catch block
}

Như đã thấy từ cú pháp trên, chúng tôi khai báo try-with-resourcescâu lệnh bằng,

  1. khai báo và khởi tạo tài nguyên trong trymệnh đề.
  2. xác định và xử lý tất cả các ngoại lệ có thể được ném ra khi đóng tài nguyên.

Lưu ý: Câu lệnh try-with-resources đóng tất cả các tài nguyên triển khai giao diện AutoClosable .

Hãy để chúng tôi lấy một ví dụ thực hiện try-with-resourcescâu lệnh.

Ví dụ 1: thử tài nguyên

import java.io.*;

class Main {
  public static void main(String[] args) {
    String line;
    try(BufferedReader br = new BufferedReader(new FileReader("test.txt"))) {
      while ((line = br.readLine()) != null) {
        System.out.println("Line =>"+line);
      }
    } catch (IOException e) {
      System.out.println("IOException in try block =>" + e.getMessage());
    }
  }
}

Kết quả nếu không tìm thấy tệp test.txt.

IOException in try-with-resources block =>test.txt (No such file or directory)

Xuất ra nếu tệp test.txt được tìm thấy.

Entering try-with-resources block
Line =>test line

Trong ví dụ này, chúng tôi sử dụng một phiên bản của BufferedReader để đọc dữ liệu từ test.txttệp.

Khai báo và khởi tạo BufferedReader bên trong try-with-resourcescâu lệnh đảm bảo rằng thể hiện của nó được đóng bất kể trycâu lệnh hoàn thành bình thường hay ném một ngoại lệ.

Nếu một ngoại lệ xảy ra, nó có thể được xử lý bằng cách sử dụng các khối xử lý ngoại lệ hoặc từ khóa ném .

Các trường hợp ngoại lệ bị triệt tiêu

Trong ví dụ trên, các ngoại lệ có thể được ném ra khỏi try-with-resourcescâu lệnh khi:

  • The file test.txt is not found.
  • Closing the BufferedReader object.

Một ngoại lệ cũng có thể được ném ra khỏi trykhối vì quá trình đọc tệp có thể không thành công vì nhiều lý do bất kỳ lúc nào.

Nếu các ngoại lệ được ném ra từ cả trykhối và try-with-resourcescâu lệnh, thì ngoại lệ từ trykhối sẽ được ném ra và ngoại lệ từ try-with-resourcescâu lệnh bị loại bỏ.

Truy xuất các trường hợp ngoại lệ bị loại bỏ

Trong Java 7 trở lên, các ngoại lệ bị chặn có thể được truy xuất bằng cách gọi Throwable.getSuppressed()phương thức từ ngoại lệ do trykhối ném ra .

Phương thức này trả về một mảng tất cả các ngoại lệ bị loại bỏ. Chúng tôi nhận được các ngoại lệ bị đàn áp trong catchkhối.

catch(IOException e) {
  System.out.println("Thrown exception=>" + e.getMessage());
  Throwable[] suppressedExceptions = e.getSuppressed();
  for (int i=0; i<suppressedExceptions.length; i++) {
    System.out.println("Suppressed exception=>" + suppressedExceptions[i]);
  }
}

Ưu điểm của việc sử dụng thử tài nguyên

Dưới đây là những lợi thế của việc sử dụng thử với tài nguyên:

1. khối cuối cùng không cần thiết để đóng tài nguyên

Trước khi Java 7 giới thiệu tính năng này, chúng tôi phải sử dụng finallykhối để đảm bảo rằng tài nguyên được đóng lại để tránh rò rỉ tài nguyên.

Đây là một chương trình tương tự như Ví dụ 1 . Tuy nhiên, trong chương trình này, chúng tôi đã sử dụng khối cuối cùng để đóng tài nguyên.

Ví dụ 2: Đóng tài nguyên bằng khối cuối cùng

import java.io.*;

class Main {
  public static void main(String[] args) {
    BufferedReader br = null;
    String line;

    try {
      System.out.println("Entering try block");
      br = new BufferedReader(new FileReader("test.txt"));
      while ((line = br.readLine()) != null) {
        System.out.println("Line =>"+line);
      }
    } catch (IOException e) {
      System.out.println("IOException in try block =>" + e.getMessage());
    } finally {
      System.out.println("Entering finally block");
      try {
        if (br != null) {
          br.close();
        }
      } catch (IOException e) {
        System.out.println("IOException in finally block =>"+e.getMessage());
      }

    }
  }
}

Đầu ra

Entering try block
Line =>line from test.txt file
Entering finally block 

Như chúng ta có thể thấy từ ví dụ trên, việc sử dụng finallykhối để dọn dẹp tài nguyên làm cho mã phức tạp hơn.

Chú ý cả try...catchkhối trong finallykhối? Điều này là do một IOExceptioncũng có thể xảy ra trong khi đóng BufferedReadercá thể bên trong finallykhối này nên nó cũng bị bắt và xử lý.

Câu try-with-resourceslệnh thực hiện quản lý tài nguyên tự động . Chúng ta không cần phải đóng tài nguyên một cách rõ ràng vì JVM tự động đóng chúng. Điều này làm cho mã dễ đọc hơn và dễ viết hơn.

2. thử tài nguyên với nhiều tài nguyên

Chúng ta có thể khai báo nhiều tài nguyên trong try-with-resourcescâu lệnh bằng cách phân tách chúng bằng dấu chấm phẩy;

Ví dụ 3: thử với nhiều tài nguyên

import java.io.*;
import java.util.*;
class Main {
  public static void main(String[] args) throws IOException{
    try (Scanner scanner = new Scanner(new File("testRead.txt")); 
      PrintWriter writer = new PrintWriter(new File("testWrite.txt"))) {
      while (scanner.hasNext()) {
        writer.print(scanner.nextLine());
      }
    }
  }
}

Nếu chương trình này thực thi mà không tạo ra bất kỳ ngoại lệ nào, Scannerđối tượng sẽ đọc một dòng từ testRead.txttệp và ghi nó vào một testWrite.txttệp mới .

Khi nhiều khai báo được thực hiện, try-with-resourcescâu lệnh đóng các tài nguyên này theo thứ tự ngược lại. Trong ví dụ này, PrintWriterđối tượng được đóng trước và sau đó Scannerđối tượng được đóng.

Nâng cao tính năng thử với tài nguyên trong Java 9

Trong Java 7, có một hạn chế đối với try-with-resourcescâu lệnh. Tài nguyên cần được khai báo cục bộ trong khối của nó.

try (Scanner scanner = new Scanner(new File("testRead.txt"))) {
  // code
}

Nếu chúng ta khai báo tài nguyên bên ngoài khối trong Java 7, nó sẽ tạo ra một thông báo lỗi.

Scanner scanner = new Scanner(new File("testRead.txt"));
try (scanner) {
  // code
}

Để đối phó với lỗi này, Java 9 đã cải tiến try-with-resourcescâu lệnh để tham chiếu của tài nguyên có thể được sử dụng ngay cả khi nó không được khai báo cục bộ. Đoạn mã trên bây giờ sẽ thực thi mà không có bất kỳ lỗi biên dịch nào.









Gõ tìm kiếm nhanh...