Adding a little bit more detail to my comments
A try-with block is defined as follows:
try(...) {
...
}
where the argument in parenthesis needs to be an instance of java.lang.AutoCloseable. An example is the class java.io.InputStream, which is also the class for System.in.
A try-with attempts to automatically close its provided resource, once the block is left. Depending on the used resource, it closes all its own child resources as well.
Taking your example, you have try(Scanner scanner = new Scanner(System.in)), which uses Scanner as resource. The scanner itself uses System.in as resource. Once the try block is left (when } is reached) it tries to close its resources, which is the Scanner instance. This instance also tries to close its resource, the System.in.
Once System.in is closed, you can't get any input from the console anymore (at least not with some additional work, I think...).
Concretely, in your second example:
while (!input.equals("q")) {
try(Scanner scanner = new Scanner(System.in)){
...
} // <--- The block is left, scanner is closed, System.in is closed
} // <-- start a new iteration
Here after just one iteration, System.in gets closed. Sure, you create a new Scanner in the next iteration, but System.in remains closed, that's why you get your exception in this case.
Your third example:
try(Scanner scanner = new Scanner(System.in)){
while (!input.equals("q")) {
...
} // <-- start a new iteration, while still in the same try block
} // <-- only after the while, your resources are closed
Here you're looping your while, while still being inside try. So no resource gets closed, until you leave while and try. That means, the one Scanner remains intact and with it the one System.in. This allows you to keep reading from the console until you're done looping.
Adding a little bit more detail to my comments
A try-with block is defined as follows:
try(...) {
...
}
where the argument in parenthesis needs to be an instance of java.lang.AutoCloseable. An example is the class java.io.InputStream, which is also the class for System.in.
A try-with attempts to automatically close its provided resource, once the block is left. Depending on the used resource, it closes all its own child resources as well.
Taking your example, you have try(Scanner scanner = new Scanner(System.in)), which uses Scanner as resource. The scanner itself uses System.in as resource. Once the try block is left (when } is reached) it tries to close its resources, which is the Scanner instance. This instance also tries to close its resource, the System.in.
Once System.in is closed, you can't get any input from the console anymore (at least not with some additional work, I think...).
Concretely, in your second example:
while (!input.equals("q")) {
try(Scanner scanner = new Scanner(System.in)){
...
} // <--- The block is left, scanner is closed, System.in is closed
} // <-- start a new iteration
Here after just one iteration, System.in gets closed. Sure, you create a new Scanner in the next iteration, but System.in remains closed, that's why you get your exception in this case.
Your third example:
try(Scanner scanner = new Scanner(System.in)){
while (!input.equals("q")) {
...
} // <-- start a new iteration, while still in the same try block
} // <-- only after the while, your resources are closed
Here you're looping your while, while still being inside try. So no resource gets closed, until you leave while and try. That means, the one Scanner remains intact and with it the one System.in. This allows you to keep reading from the console until you're done looping.
Try this:
String input = "";
try (Scanner scanner = new Scanner(System.in)) {
while (!input.equals("q")) {
System.out.print("Input: ");
input = scanner.nextLine();
System.out.println("Input was: " + input);
}
}
You can use every class thats implements Closeable or AutoCloseable in try-with-resources, When code reaches the end of the try call, It call close() function of the Scanner class in our example.
java - Surrounding a Scanner with try-with-resources - Stack Overflow
try with resources - Does Java scanner implement Closeable? - Stack Overflow
Why do I have to do a try/catch when I use a .txt file in a scanner?
Resource leak with java.util.Scanner, but closing it causes the program to malfunction.
Videos
try-with-resources provides a guarantee that AutoCloseable resources, like Scanner, will always be closed. Closing is added implicitly by javac approx. as
Scanner inputFile = new Scanner(file);
try {
while (inputFile.hasNext()) {
....
}
} finally {
inputFile.close();
}
BTW there is a problem in your code that Netbeans failed to notice. Scanner's methods do not throw IOException but supppress it. Use Scanner.ioException to check if any exception occurred during reading file.
Read this, re Java 7's try-with-resource block.
The try-with-resources statement ensures that each resource is closed at the end of the statement.
Java 6 doesn't support try-with-resources; you must explicitly close the IO stream.
I am a relative beginner, and I do not understand why do I have to do this. Almost everything can throw an exception all the time. Why do I have to do this in order to use it at all?