Should you close a Scanner that wraps System.in, and what are the consequences either way?
answer
- close() cascades to the underlying source
- Closing a System.in Scanner closes standard input for good
- File/stream Scanner -> close (try-with-resources)
- String Scanner -> nothing to release
- Static-analyzer 'unclosed Scanner' on System.in is a false positive
basics
~20 sClosing a Scanner also closes its underlying source. For a Scanner over System.in that means standard input is closed and can't be read again, so usually you don't close it. For a Scanner over a File, you should close it to free the file.
solid answer
~40 sScanner implements Closeable/AutoCloseable, and closing it closes the underlying source if that source is itself Closeable. For System.in this is the catch: closing the Scanner closes standard input for the whole JVM, so any later attempt to read System.in (even with a new Scanner) fails or returns end-of-input. In a typical console app you therefore deliberately do not close the Scanner; the OS reclaims standard input at exit. For a Scanner over a File or other owned resource, you absolutely should close it — ideally with try-with-resources — to release the file handle and avoid leaks. Static analyzers like to flag the unclosed System.in Scanner as a resource leak, which is a false positive in this specific case; document the intent or suppress it knowingly rather than closing System.in by reflex.
code
java · 9 lines// File source: own it, close it.
try (Scanner sc = new Scanner(new File("data.txt"))) {
while (sc.hasNextLine()) System.out.println(sc.nextLine());
} // auto-closed, file handle released
// System.in: do NOT close — it would close standard input for the whole JVM.
Scanner in = new Scanner(System.in);
int n = in.nextInt();
// no in.close();go deeper
Knows Scanner has a close() method and that closing a System.in Scanner can stop further keyboard input.
Explains that close() cascades to the underlying source and decides correctly: close File-backed Scanners (try-with-resources), do not close System.in.
Articulates the resource-ownership rule, recognizes the static-analyzer false positive on System.in, and structures input code to own and release resources cleanly.
Defines team guidance for resource handling and suppression conventions, and chooses appropriate input abstractions so shared streams like System.in are managed safely across a codebase.
## The general rule `Scanner` implements `Closeable` (and therefore `AutoCloseable`). When you call `close()` on a Scanner, **if the source it wraps also implements `Closeable`, that source is closed too.** This cascading close is the key to the whole question. ### Terms - **`Closeable`/`AutoCloseable`**: interfaces meaning "this object holds a resource that should be released when you are done." `AutoCloseable` is what lets an object be used in **try-with-resources** (a `try (...) { }` form that auto-closes at the end). - **Underlying source**: the thing the Scanner reads from — `System.in`, a `File`'s stream, a `String`, etc. A `String` is not closeable; a stream is. - **`System.in`**: the JVM's single standard-input stream, shared by the whole program. ## Case 1 — Scanner over System.in If you write: ```java Scanner sc = new Scanner(System.in); // ... read input ... sc.close(); // <-- this also closes System.in! ``` Closing the Scanner closes `System.in`. Because `System.in` is a **single, process-wide stream that cannot be reopened**, any later read — even from a brand-new `new Scanner(System.in)` — will see end-of-input or throw. So: - In a normal interactive/console program, **do not close** a Scanner wrapping `System.in`. Let the program end; the operating system reclaims the stream. - If you must read `System.in` from multiple places, share **one** Scanner and never close it. ### The static-analysis false positive Tools like SpotBugs, SonarLint, or IDE inspections often warn "resource leak: Scanner is never closed." For a `System.in` Scanner this warning is **a false positive** — closing it would be the actual bug. The right move is to leave it open and, if needed, suppress the warning with a comment explaining why, rather than closing standard input by reflex. ## Case 2 — Scanner over a File or other owned resource Here the source *is* an OS resource (a file handle) that you opened and own. You **must** close it, or you leak file descriptors. Use **try-with-resources** so it closes even on exception: ```java try (Scanner sc = new Scanner(new File("data.txt"))) { while (sc.hasNextLine()) process(sc.nextLine()); } // sc.close() runs automatically, releasing the file ``` ## Case 3 — Scanner over a String `new Scanner("some text")` wraps a `String`, which is not a closeable resource. Closing it is harmless and unnecessary; there is nothing to release. ## The decision rule Ask: **"Does this Scanner own a resource I opened and that should be released?"** - Over a **File/stream I opened** -> yes, close it (try-with-resources). - Over **System.in** -> no, don't close it (closing kills shared standard input). - Over a **String** -> doesn't matter. The single principle behind all three: closing a Scanner closes its source, so close it exactly when — and only when — you want that source closed.
- Why is an IDE warning about an unclosed Scanner over System.in often a false positive?Because closing it would close the shared, non-reopenable System.in stream, breaking any later input. Leaving it open is intentional, so the leak warning does not apply; suppress it with an explanatory comment if needed.
- What is the safest way to close a Scanner over a file?Use try-with-resources: try (Scanner sc = new Scanner(file)) { ... }. It calls close() automatically at the end of the block, even if an exception is thrown, releasing the file handle.
A Scanner is like a tap fitted onto a pipe. Closing the tap on your own garden hose (a File) is tidy. But System.in is the building's main water line shared by everyone; shut that valve and no one in the program gets water again.
saying these in an interview costs you the question
- Always closing every Scanner by habit, including one wrapping System.in
- Thinking System.in can be reopened after a Scanner closes it
- Believing close() only releases Scanner's own buffers, not the underlying stream
- Leaving a File-backed Scanner unclosed and leaking file descriptors