Home > Mobile >  Scanner is never closed in method, but I think it does actually close every time the method ends?
Scanner is never closed in method, but I think it does actually close every time the method ends?

Time:11-17

public static void maxintRecursive(int max) {

// create scanner
        Scanner in = new Scanner(System.in);

// asks user for integer input
        int a = in.nextInt();



// checks if integer input satisfies exit condition, closes scanner, prints max and returns
        if (a <= 0) {
            in.close();
            System.out.println("Max int is: "   max);
            return;
        }

// checks if input is greater than previous max registered int
        if (a > max) {
            max = a;
        }
// calls itself again
        maxintRecursive(max);
    }

I can compile and run it successfully, but at line 3 it underlines "in" saying that it's never closed However, this method keeps calling itself until you reach the exit condition (a <=0) under which the scanner does in fact get closed

Is it an error? Is it actually never getting closed and I'm getting a memory leak?

Should I pass a scanner in the method from the main, or would it be the same?

This recursive method asks the user for an integer input and returns the maximum integer received once the user inputs 0 or less

I created a scanner inside the method and closed it when the recursive method reaches its exit condition

I expected the scanner to be closed by my code inside the exit condition, but VS Code says it never gets closed

CodePudding user response:

Each time method its called, it creates its own local variables. For instance if you have method like

void foo(int n) { 
    int x = n   1; 
    if (x < 2) 
        foo(x); 
}

and you call it like foo(0); then while executing it will have its own two local variables n=0 (method parameter) and x = n 1 = 0 1 = 1 (declared in body of method).
Then when you invoke recursively foo(x); which will end up as foo(1) that invocation will create another set of n x local variables which will be holding values n=1 x=2.

Similarly in your case, each time you call maxintRecursive method it creates its own separate Scanner in = new Scanner(...) object. So if you called your method N times, the N Scanner objects ware created (all of them reading from System.in). Even if you call in.close(); in method handling if (a <= 0) it will only close Scanner created by that recursive invocation. Other Scanners, created in previous method calls will never be closed.

Possible solution could be also adding in.close(); at the end of your method (after recursive call), which will ensure that each method will close its own Scanner.

But preferred solution would be preventing creating so many Scanners in the first place. Instead create one in main method and pass it to recursive method as parameter. Since it will be passed Java will not force you to close that scanner in method itself, but in scope where it was created (the main method).

To do this you need to let maxintRecursive accept Scanner as parameter by modifying its declaration like

public static void maxintRecursive(int max, Scanner in) {
    //...
}

This way all you need now is something like

public static main(String[] args){
    Scanner scanner = new Scanner(System.in);
    maxintRecursive(-1, scanner);
    scanner.close();
}

BTW another reason we avoid creating Scanner which handles System.in inside our own methods is fact that closing such Scanner by that method would also close System.in. This means when you will try to call your method again it will create Scanner which will try to read from already close System.in. Again, preferred solution in such case is to pass Scanner handling System.in as method parameter.

  • Related