Java - Closing Scanner and Resource Leak

I am learning Java and working on some projects for fun. One of the problems that I have encountered is that when I use the Scanner object, Eclipse warns me that:

Resource Leak: Scan never closes.

So I added scan.close(); at the end of my code and takes care of the warning.

The problem arises because I have other classes in the same package that also use scanner objects, and Eclipse tells me to close the scanner in these classes accordingly. However, when I do this, it looks like it closes ALL scanner objects, and I get errors at runtime.

Here is an example of what causes the error:

 import java.util.Scanner; public class test2 { public static void main(String [] args) { Scanner scan = new Scanner(System.in); int test = 0; do { //Do stuff test = scan.nextInt(); System.out.println(test); scanTest scanTest = new scanTest(); scanTest.test(); } while (test != 0); scan.close(); } } import java.util.Scanner; public class scanTest { public void test() { Scanner scanner = new Scanner(System.in); int blah = scanner.nextInt(); System.out.println(blah); scanner.close(); } } 

After the scanner is closed in the scanTest class and the do loop in test2 is entered again, in the line test = scan.nextInt();

I tried to move the creation of the scanner object to the do loop only to create a new object every time, but the error still occurs.

I don’t know why this is happening or how I can make sure that all the I / O objects are closed without problems.

One post I met mentioned that when System.in closed, I cannot open it again. If so, do I just need to make sure that the scanner object with System.in is closed at the very end of the program and @suppress are all the other scanner warnings in other classes? Or will it still leave all of these scanner objects open (bad)?

+8
java java.util.scanner eclipse
source share
3 answers

Firstly, it is not a memory leak.

Secondly, when you close the stream wrapper, the default implementation is to close the stream that it wraps. This means that the first time you close the scanner (as written), yes, you close System.in.

In general, I would like to avoid closing System.in if they made sense to read from System.in again. The best way to do this depends on your program.

You can copy information from System.in to some buffer, and then scan the buffer. You cannot close the scanner by reusing it in other places. You can even turn off the garbage collection scanner and create several new scanners on System.in.

These solutions are not all equivalent; some are considered much better than others; but it all depends on the calling program. Experiment with a few, and if you have a problem, open a new StackOverflow question in which you will see the relevant parts of the code, a description of the problem, an example input and incorrect output (along with the desired result).

Good luck.

+3
source share

Yes, when you close the scanner, you will close the underlying thread (in this case System.in). To avoid this, create a global scanner variable that can be used by all classes or have a central point to turn off the scanner (just before the program exits it will be ideal).

+3
source share

Do not call all your scanners the same. If you have several in one thing, for example:

 import java.util.Random; import java.util.Scanner; public class DayThree { public static void main(String[] args) { **Scanner textScanner = new Scanner(System.in);** // boolean operands // String(or objects) .equals() "this".equals("that") false // primitive data types == 'a'=='a' -> true 5==6 false // != 'a'!='a' -> false 5!=6 true // ! !(true) -> false !(false) true // > 5 > 4 -> true 'a' > 'b' false // < 5 < 4 -> false // <= // >= // && -> and 5 < 6 && 7 > 10 -> false // if either side of and is false the outcome is false // || -> or 5 < 6 || 7 > 10 -> true // if either side of or is true the outcome is true //System.out.println(!(5 < 10) && (7>3) || (true && false || true)); /* <-- this is a multi line comment System.out.println("What is the most amazing show on tv this week? "); String show = textScanner.nextLine().toLowerCase(); //this is case sensitive show = show.toLowerCase(); // changes the strng to a lowercase version show = show.toUpperCase(); if(show.equalsIgnoreCase("game of thrones")){ // .equalsIgnoreCase( ignores caps/lower) System.out.println("Yes it is!"); } else{ System.out.println("You are wrong."); System.out.println(show + " is clearly inferior to Game of Thrones."); } System.out.println("Who is your favorite character in " + show + "."); String character = textScanner.nextLine().toLowerCase(); if(character.contains("dragon")){ System.out.println("CGI magic is so cool!"); } else if(character.contains("lanister")){ System.out.println("Wrong house."); } else{ System.out.println(character + "is pretty cool I guess..."); } */ // asdf alternate multi line comment use ctrl + / on highlighted text. // doing this a second time undoes the comment // sdaf // asdf // asdf // asdf // 1. ask about favorite something (pet) // 2. save that into a string all lowercase // 3. have a series of if else (x3) and else statements about the something //NOTE: DO NOT END CONDITIONALS WITH ; example: if(boolean); IS WRONG. **Scanner numScanner = new Scanner(System.in);** // the variable tells you what to use it for Random rand = new Random(); // this makes a new random object System.out.println("Pick a number."); int num = numScanner.nextInt(); int sNum = rand.nextInt(9) + 1; // gives me a random num between 1-10 // nextInt(bound)gives you a num from 0-bound //adding one gives you a num from 1 - bound + 1 if(num > sNum){ System.out.println("Too high"); System.out.println("The number was " + sNum); } else if(num < sNum){ System.out.println("Too low"); System.out.println("The number was " + sNum); } else{ System.out.println("Wow are you psychic? "); } textScanner.close(); numScanner.close(); }//main method } 

Put *scanner name goes here*.close(); for each of your scanners. If they all have the same name, change those that are different from others and others.

0
source share

All Articles