Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> Java

ARM (Automatic Resource Management) trong Java – try-with-resources

ARM (Automatic Resource Management) hay try-with-resources (Java 7+) tự động đóng resource implement AutoCloseable.

Vấn đề trước Java 7: finally block


// Cũ – dễ quên close, code rối
FileInputStream fis = null;
try {
    fis = new FileInputStream("file.txt");
    // đọc file
} catch (IOException e) {
    e.printStackTrace();
} finally {
    if (fis != null) try { fis.close(); } catch (IOException ignored) {}
}

Giải pháp: try-with-resources


// Java 7+ – tự động close ở cuối block
try (FileInputStream fis = new FileInputStream("file.txt")) {
    // đọc file
} catch (IOException e) {
    e.printStackTrace();
}
// fis.close() được gọi tự động (da dù có exception)

Nhiều resource (Java 7+)


try (FileInputStream in = new FileInputStream("in.txt");
     FileOutputStream out = new FileOutputStream("out.txt")) {
    byte[] buf = new byte[1024];
    int len;
    while ((len = in.read(buf)) > 0) {
        out.write(buf, 0, len);
    }
} // in.close() và out.close() tự động gọi (reverse order)

Java 9+: Effectively final variables


// Khai báo ngoài, dùng trong try
FileInputStream fis = new FileInputStream("file.txt");
try (fis) { // không cần khai báo mới
    // dùng fis
}

Quy tắc quan trọng

  • Resource phải implement AutoCloseable (hoặc Closeable extends nó)
  • Close order: ngược thứ tự khai báo (LIFO)
  • Exception từ close() bị suppressed nếu try block cũng ném exception – dùng ex.getSuppressed() để lấy
  • Không gán null vào resource trong try block

Ví dụ Suppressed Exception


try (MyResource r = new MyResource()) {
    throw new IOException("Lỗi trong try");
} catch (IOException e) {
    for (Throwable s : e.getSuppressed()) {
        System.out.println("Suppressed: " + s); // close() exception
    }
}

Custom Resource


class MyResource implements AutoCloseable {
    @Override
    public void close() throws Exception {
        System.out.println("Closing resource...");
        // throw new IOException("Close failed"); // test suppressed
    }
}

Best practice: Luôn dùng try-with-resources cho file, stream, socket, DB connection, lock...