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ặcCloseableextends 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ùngex.getSuppressed()để lấy - Không gán
nullvà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...