Phương thức hoàn thiện, giao diện có thể đóng và câu lệnh dùng thử tài nguyên (Java 7) - 1

"Chào, Amigo!"

"Tôi vừa quyết định thảo luận về phương thức finalize () với bạn."

"Nếu bạn còn nhớ, hoàn thiện () là một phương thức đặc biệt được gọi bởi một đối tượng trước khi trình thu gom rác phá hủy nó."

"Mục đích chính của phương pháp này là giải phóng các tài nguyên không phải Java bên ngoài đã sử dụng bằng cách đóng tệp, luồng I/O, v.v."

"Thật không may, phương pháp này không đáp ứng được kỳ vọng của chúng tôi. Máy ảo Java có thể trì hoãn việc hủy một đối tượng, cũng như gọi phương thức hoàn thiện, miễn là nó muốn. Hơn nữa, nó không đảm bảo rằng phương thức này sẽ được không được gọi. Có rất nhiều tình huống mà nó không được gọi, tất cả là do «tối ưu hóa»."

"Tôi có hai tài liệu tham khảo cho bạn:"

Joshua Bloch đã viết một bài báo hay về phương pháp này: link
Tôi sẽ diễn giải một đoạn trích ngắn:

  1. finalize() chỉ có thể được sử dụng trong hai trường hợp:
    1. Để xác minh hoặc dọn dẹp tài nguyên bằng ghi nhật ký.
    2. Khi làm việc với mã gốc không quan trọng đối với rò rỉ tài nguyên.
  2. finalize() làm cho GC chậm hơn 430 lần trong việc dọn dẹp các đối tượng
  3. finalize() có thể không được gọi
Nếu tôi nói trong một cuộc phỏng vấn rằng hoàn thiện là một cái nạng có hại và nguy hiểm mà chính sự tồn tại của nó đã gây nhầm lẫn, liệu tôi có đúng không?

"Chà, điều đó đã làm cho ngày của tôi, Ellie."

"Java 7 có một câu lệnh mới để thay thế phương thức hoàn thiện . Nó được gọi là try-with-resources . Nó không thực sự là một sự thay thế cho finalize , mà nó là một cách tiếp cận khác."

"Nó giống như thử bắt, nhưng với tài nguyên?"

"Nó gần giống như try-catch . Vấn đề là, không giống như phương thức finalize (), khối cuối cùng trong câu lệnh try- catch-cuối cùng luôn được thực thi. Các lập trình viên cũng đã sử dụng kỹ thuật này khi họ cần giải phóng tài nguyên, đóng chủ đề, v.v.

"Đây là một ví dụ:"

InputStream is = null;
try
{
 is = new FileInputStream("c:/file.txt");
 is.read(…);
}
finally
{
 if (is != null)
 is.close();
}

"Bất kể khối try được thực thi đúng hay có ngoại lệ, khối cuối cùng sẽ luôn được gọi và có thể giải phóng các tài nguyên bị chiếm dụng ở đó."

"Vì vậy, trong Java 7, quyết định đã được đưa ra để biến phương pháp này thành chính thức, như vậy:"

try(InputStream is = new FileInputStream("c:/file.txt"))
{
 is.read(…);
}

"Câu lệnh thử đặc biệt này được gọi là thử với tài nguyên (tương tự như cách các bộ sưu tập có một thay thế cho foreach được gọi )."

"Lưu ý rằng sau lần thử có các dấu ngoặc đơn nơi các biến được khai báo và các đối tượng được tạo. Các đối tượng này có thể được sử dụng bên trong khối thử được biểu thị bằng dấu ngoặc nhọn. Khi khối thử được thực thi xong, bất kể nó kết thúc bình thường hay ở đó là một ngoại lệ, phương thức close() sẽ được gọi trên bất kỳ đối tượng nào được tạo bên trong dấu ngoặc đơn."

"Thật thú vị! Ký hiệu này cô đọng hơn nhiều so với ký hiệu trước. Tôi không chắc mình đã hiểu nó."

"Nó không khó như bạn nghĩ."

"Vì vậy, tôi có thể chỉ định lớp của từng đối tượng trong ngoặc đơn không?"

"Vâng, tất nhiên, nếu không thì dấu ngoặc đơn sẽ ít được sử dụng."

"Và nếu tôi cần gọi một phương thức khác sau khi thoát khỏi khối thử, tôi sẽ đặt nó ở đâu?"

"Mọi thứ tinh tế hơn một chút ở đây. Java 7 giới thiệu giao diện sau:"

public interface AutoCloseable
{
 void close() throws Exception;
}

"Lớp của bạn có thể triển khai giao diện này. Và sau đó bạn có thể sử dụng các đối tượng của nó bên trong câu lệnh thử tài nguyên. Chỉ những đối tượng như vậy mới có thể được tạo bên trong dấu ngoặc đơn của câu lệnh thử tài nguyên cho «đóng tự động»."

"Nói cách khác, tôi cần ghi đè phương thức đóng và viết mã trong đó để «dọn dẹp» đối tượng của mình và tôi không thể chỉ định phương thức khác?"

"Đúng. Nhưng bạn có thể chỉ định một số đối tượng—chỉ cần phân tách chúng bằng dấu chấm phẩy:"

try(
InputStream is = new FileInputStream("c:/file.txt");
OutputStream os = new FileOutputStream("c:/output.txt")
)
{
 is.read(…);
 os.write(…);
}

"Điều đó tốt hơn, nhưng không tuyệt như tôi mong đợi."

"Không tệ đến thế đâu. Cậu sẽ quen thôi. Lâu dần."