Hướng dẫn php try-with-resources - tài nguyên dùng thử php

Câu lệnh try-with-resources là câu lệnh try dùng để khai báo một hoặc nhiều tài nguyên. Một tài nguyên là một đối tượng trong đó phải được đóng sau khi chương trình kết thúc với nó. Câu lệnh try-with-resources đảm bảo rằng mỗi tài nguyên sẽ được đóng ngay khi kết thúc câu lệnh. Bất kỳ đối tượng nào thực thi java.lang.AutoCloseable, bao gồm cả những đối tượng thực thi java.io.Closeable, thì đều được sử dụng như là một nguồn tài nguyên.try-with-resources là câu lệnh try dùng để khai báo một hoặc nhiều tài nguyên. Một tài nguyên là một đối tượng trong đó phải được đóng sau khi chương trình kết thúc với nó. Câu lệnh try-with-resources đảm bảo rằng mỗi tài nguyên sẽ được đóng ngay khi kết thúc câu lệnh. Bất kỳ đối tượng nào thực thi java.lang.AutoCloseable, bao gồm cả những đối tượng thực thi java.io.Closeable, thì đều được sử dụng như là một nguồn tài nguyên.

Ví dụ dưới đây đọc dòng đầu tiên từ một tập tin. Nó sử dụng một thể hiện của BufferedReader để đọc dữ liệu từ tập tin. BufferedReader là một tài nguyên và phải được đóng sau khi chương trình kết thúc với nó:

static String readFirstLineFromFile(String path) throws IOException {    try (BufferedReader br = new BufferedReader(new FileReader(path))) {        return br.readLine();    }}
    try (BufferedReader br = new BufferedReader(new FileReader(path))) {
        return br.readLine();
    }
}

Trong ví dụ trên, tài nguyên được khai báo trong try-with-resources là một BufferedReader. Câu lệnh khai báo xuất hiện trong ngoặc đơn ngay sau từ khóa try. Lớp BufferedReader, từ bản Java SE 7, sẽ thực thi giao diện java.lang.AutoCloseable. Vì thể hiện của BufferedReader được khai báo trong try-with-resources, nên nó sẽ đóng bất kể là câu lệnh try hoàn thành một cách bình thường hay đột ngột (như là kết quả của phương thức try4 ném ngoại lệ try5).

Trước Java SE 7, bạn có thể sử dụng khối try6 để thực hiện điều trên. Ví dụ sau đây sử dụng khối try6 thay vì câu lệnh try-with-resources:

static String readFirstLineFromFileWithFinallyBlock(String path) throws IOException {    BufferedReader br = new BufferedReader(new FileReader(path));    try {        return br.readLine();    } finally {        if (br != null) br.close();    }}
    BufferedReader br = new BufferedReader(new FileReader(path));
    try {
        return br.readLine();
    } finally {
        if (br != null) br.close();
    }
}

Tuy nhiên, trong ví dụ trên, nếu các phương thức try9 và java.lang.AutoCloseable0 đều ném ngoại lệ, thì phương thức java.lang.AutoCloseable1 sẽ ném ngoại lệ được ném từ khối try6; ngoại lệ được ném từ khối try sẽ bị bỏ qua. Ngược lại, trong ví dụ nằm trên ví dụ này thì ở phương thức java.lang.AutoCloseable4, nếu ngoại lệ được ném ra từ cả hai khối try và try-with-resources thì phương thức java.lang.AutoCloseable4 sẽ ném ngoại lệ được ném từ khối try; ngoại lệ được ném từ khối try-with-resources sẽ bị bỏ qua. Từ bản Java SE 7 thì bạn có thể truy xuất các ngoại lệ bị bỏ qua, xin xem thêm tại phần Ngoại lệ bị bỏ qua.

Bạn có thể khai báo một hoặc nhiều tài nguyên trong câu lệnh try-with-resources. Ví dụ sau lấy tên của các tập tin được đóng gói trong file zip là java.io.Closeable1 và tạo ra một tập tin văn bản có chứa tên của các tập tin này:

public static void writeToFileZipFileContents(String zipFileName, String outputFileName) throws java.io.IOException {

    java.nio.charset.Charset charset = java.nio.charset.StandardCharsets.US_ASCII;    java.nio.file.Path outputFilePath = java.nio.file.Paths.get(outputFileName);
    java.nio.file.Path outputFilePath = java.nio.file.Paths.get(outputFileName);

    // Mở file zip và tạo đầu ra với    // câu lệnh try-with-resources
    // câu lệnh try-with-resources

    try (        java.util.zip.ZipFile zf = new java.util.zip.ZipFile(zipFileName);        java.io.BufferedWriter writer = java.nio.file.Files.newBufferedWriter(outputFilePath, charset)    ) {        // Liệt kê từng mục        for (java.util.Enumeration entries = zf.entries(); entries.hasMoreElements();) {            // Lấy tên đầu vào và ghi nó tới tập tin đầu ra            String newLine = System.getProperty("line.separator");            String zipEntryName = ((java.util.zip.ZipEntry)entries.nextElement()).getName() + newLine;            writer.write(zipEntryName, 0, zipEntryName.length());        }    }}try (
        java.util.zip.ZipFile zf = new java.util.zip.ZipFile(zipFileName);
        java.io.BufferedWriter writer = java.nio.file.Files.newBufferedWriter(outputFilePath, charset)
    )
{
        // Liệt kê từng mục
        for (java.util.Enumeration entries = zf.entries(); entries.hasMoreElements();) {
            // Lấy tên đầu vào và ghi nó tới tập tin đầu ra
            String newLine = System.getProperty("line.separator");
            String zipEntryName = ((java.util.zip.ZipEntry)entries.nextElement()).getName() + newLine;
            writer.write(zipEntryName, 0, zipEntryName.length());
        }
    }
}

Trong ví dụ trên, câu lệnh try-with-resources chứa hai khai báo được phân cách bằng dấu chấm phẩy: java.io.Closeable3 và java.io.Closeable4. Khi các khối mã trực tiếp sau nó chấm dứt hoặc là bình thường hoặc phát sinh ngoại lệ, thì các phương thức java.lang.AutoCloseable0 của các đối tượng java.io.Closeable4 và java.io.Closeable3 được tự động gọi theo thứ tự này. Lưu ý rằng các phương thức java.lang.AutoCloseable0 của các nguồn tài nguyên được gọi theo thứ tự ngược.

Ví dụ sau đây sử dụng câu lệnh try-with-resources để tự động đóng đối tượng BufferedReader0:

public static void viewTable(Connection con) throws SQLException {

    String query = "select COF_NAME, SUP_ID, PRICE, SALES, TOTAL from COFFEES";

    try (Statement stmt = con.createStatement()) {        ResultSet rs = stmt.executeQuery(query);try (Statement stmt = con.createStatement()) {
        ResultSet rs = stmt.executeQuery(query);

        while (rs.next()) {            String coffeeName = rs.getString("COF_NAME");            int supplierID = rs.getInt("SUP_ID");            float price = rs.getFloat("PRICE");            int sales = rs.getInt("SALES");            int total = rs.getInt("TOTAL");
            String coffeeName = rs.getString("COF_NAME");
            int supplierID = rs.getInt("SUP_ID");
            float price = rs.getFloat("PRICE");
            int sales = rs.getInt("SALES");
            int total = rs.getInt("TOTAL");

            System.out.println(coffeeName + ", " + supplierID + ", " + price + ", " + sales + ", " + total);        }    } catch (SQLException e) {        JDBCTutorialUtilities.printSQLException(e);    }}
        }
    } catch (SQLException e) {
        JDBCTutorialUtilities.printSQLException(e);
    }
}

Tài nguyên BufferedReader0 được sử dụng trong ví dụ trên là một phần của JDBC 4.1 và API phiên bản mới.

Lưu ý: Mỗi câu lệnh try-with-resources có thể có các khối BufferedReader3 và try6 giống như câu lệnh try thông thường. Trong try-with-resources thì bất kỳ khối BufferedReader3 hay try6 nào chạy sau các tài nguyên được khai báo thì đều bị đóng.

Ngoại lệ bị bỏ qua

Một ngoại lệ có thể được ném ra từ khối mã lệnh kết hợp với câu lệnh try-with-resources. Trong ví dụ BufferedReader0, một ngoại lệ có thể được ném từ khối try, và có thể lên đến hai ngoại lệ được ném từ try-with-resources khi nó cố đóng các đối tượng java.io.Closeable3 và java.io.Closeable4. Nếu một ngoại lệ được ném từ khối try và một hoặc nhiều ngoại lệ được ném từ khối try-with-resources thì những ngoại lệ ném từ try-with-resources sẽ bị bỏ qua, và ngoại lệ được ném bởi khối là ngoại lệ được ném bởi phương thức BufferedReader0. Bạn có thể lấy những ngoại lệ bị bỏ qua này bằng cách gọi phương thức BufferedReader9 từ ngoại lệ được ném ra bởi khối try.

Các lớp thực thi giao diện AutoCloseable hoặc Closeable

Xem các giao diện Javadoc gồm try1 và try2 cho một danh sách các lớp thực hiện một trong các giao diện này. Giao diện try2 mở rộng từ giao diện try1. Phương thức java.lang.AutoCloseable0 của giao diện try2 ném ngoại lệ kiểu try5 trong khi phương thức java.lang.AutoCloseable0 của giao diện try1 ném ngoại lệ kiểu BufferedReader0. Do đó, các lớp con của try1 có thể ghi đè hành vi này của phương thức java.lang.AutoCloseable0 để ném ngoại lệ được xác định, chẳng hạn như try5, hoặc không có ngoại lệ nào cả.