Class java.util.Scanner là một class tiện ích cho phép nhập và nhận giá trị từ màn hình console. Để sử dụng Scanner chúng ta có thể khai báo như sau:
Scanner kbd = new Scanner(System.in);
Tuy nhiên, nếu bạn đang sử dụng Eclise IDE, nó sẽ xuất một thông báo liên quan đến rò rỉ bộ nhớ ‘kbd’ is never closed”.
Bạn có thể muốn loại bỏ cảnh báo này bằng cách gọi phương thức Scanner.close() sau khi sử dụng xong. Dưới đây là một số cách mà mọi người hay làm để đóng Scanner object (lưu ý rằng đây là những điều bạn KHÔNG NÊN LÀM):
Scanner kbd = new Scanner(System.in); ... // code that uses kbd kbd.close(); // Không nên làm điều này
Một số khác còn kỹ càng hơn, sử dụng try-finally để đảm bảo Scanner được đóng đúng cách.
Scanner kbd = new Scanner(System.in); // Không nên làm điều này try { ... // code that uses kbd } finally { kbd.close(); }
Hoặc thậm chí sử dụng tính năng try-with-resource để tự động đóng Scanner
// Không nên làm điều này try (Scanner kbd = new Scanner(System.in)) { ... // code that uses kbd }
Lý do chúng ta không nên làm những điều trên là vì đối tượng System.in được mở bởi JVM và nó nên được đóng bởi nó. Nếu bạn đóng nó, thì sau này các bạn sẽ không thể sử dụng lại đối tượng System.in.
Ví dụ đoạn code sau sẽ gây lại khi Scanner đã bị đóng, mà bạn lại sử dụng lại đối tượng System.in.
import java.io.IOException; import java.util.Scanner; class AssertDemo { public static void main(String[] args) throws IOException { Scanner scanner = new Scanner(System.in); scanner.close(); System.out.println(System.in.available()); } }
Output
Exception in thread "main" java.io.IOException: Stream closed
Làm sao để ẩn thông báo này?
Có một số cách để chúng ta có thể giải quyết trong trường hợp này:
1 – Bỏ qua thông báo này, nếu đã hiểu rõ vấn đề thì chúng ta hoàn toàn có thể bỏ qua thông báo này mà không cần xử lý thêm bất cứ điều gì. Tuy nhiên đối với những cảnh báo khác thì hãy nhớ xem xét nhé.
2 – Chặn cảnh báo bằng annotation. Bạn có thể sử dụng chú thích @SuppressWarnings (“resource”) để loại bỏ cảnh báo.
@SuppressWarnings("resource") public static String getKeyboardInput() { Scanner kbd = new Scanner(System.in); ... }
Nhược điểm của cách này là khiến bạn phải sử dụng @SuppressWarnings ở rất nhiều nơi sử dụng Scanner object. Dẫn đến mã nguồn trở nên lộn xộn và mã xấu.
3 – Khai báo một biến static và sử dụng lại ở tất cả những nơi cần thiết. Bạn sẽ không nhận được cảnh báo về rò rỉ bộ nhớ khi không đóng Scanner object nếu khai báo nó là một biến statjc class. Việc này khiến cho mã nguồn của bạn có ý nghĩa hơn khi chúng ta chỉ cần khởi tạo Scanner một lần và sử dụng lại trong những lần khác, nơi khác.
public ConsoleProgram { public static final Scanner kbd = new Scanner(System.in); }
Nguồn
https://coderanch.com/wiki/678613/Don-close-Scanner-tied-System