skip to content

Should you close a Scanner that wraps System.in, and what are the consequences either way?

level: middleimportance: should knowfreq 40%

answer

  1. close() cascades to the underlying source
  2. Closing a System.in Scanner closes standard input for good
  3. File/stream Scanner -> close (try-with-resources)
  4. String Scanner -> nothing to release
  5. Static-analyzer 'unclosed Scanner' on System.in is a false positive

basics

~20 s

Closing 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 s

Scanner 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
java
// 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

for a junior

Knows Scanner has a close() method and that closing a System.in Scanner can stop further keyboard input.

for a middle

Explains that close() cascades to the underlying source and decides correctly: close File-backed Scanners (try-with-resources), do not close System.in.

for a senior

Articulates the resource-ownership rule, recognizes the static-analyzer false positive on System.in, and structures input code to own and release resources cleanly.

for a principal

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

context