问题
I\'m learning Java and working on some projects for fun. One issue that I have run in to is that when I use a Scanner
object Eclipse warns me that:
Resource Leak: \'scan\' is never closed.
So, I added a scan.close();
at the end of my code and that takes care of the warning.
The problem comes in because I have other classes in the same package that also use scanner objects and and Eclipse tells me to close scanner in those classes respectively. However, when I do that it seems like it closes ALL of the scanner objects and I get errors during run time.
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 scanner is closed in the scanTest
class and the do loop in test2
is entered again an error occurs at the line test = scan.nextInt();
I tried moving the creation of the scanner object into the do loop just to make a new object every time as well but the error still occurs.
Not sure why this is happening or how I can make sure all my I/O objects are closed out without running into problems.
One post I came across mentioned that when System.in
is closed I cannot be re-opened. If this is the case would I just need to make sure a scanner object with System.in is closed at the very end of the program and @suppress all of the other scanner warnings in other classes? Or would that still leave all those scanner objects open (bad)?
回答1:
First, this is no memory leak.
Second, when you close a stream wrapper, the default implementation is for it to close the stream that it wraps. This means that the first time you close your Scanner (as it is written), yes, you close System.in.
In general, one would like to avoid closing System.in if they were meaning to read from System.in again. The best way to go about this depends on your program.
One might copy the information from System.in into a buffer of some sort and then scan the buffer. One might not close the Scanner, reusing it in other locations. One might even de-reference the Scanner for garbage collection and create multiple 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 run into a problem, open a new StackOverflow question where you show the relevant portions of your code, a description of the problem, the example input, and the wrong output (along with the desired output).
Good luck.
回答2:
Yes, when you close a scanner you will be closing the underlying stream (in this case System.in). To avoid this, either create a global variable of scanner which can be used by all classes or have a central point for shutting down the scanner (just before the program exits would be ideal)
回答3:
Don't name all your scanners the same. If you have multiple in one thing like this:
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 the *scanner name goes here*.close();
for each one of your scanners. If they all have the same name then change the ones that do something different from and other scanner.
来源:https://stackoverflow.com/questions/23621668/java-closing-scanner-and-resource-leak