Moawia307
Moawia307

Reputation: 91

life and death of an object explanation

The code below gives me a warning on Eclipse: "resource leak, input is never closed":

Code: 1

import java.util.Scanner;

public class Ex {
    public void sum() {
        Scanner input = new Scanner(System.in);
    }
}

I found that declaring the input variable in the class level does the trick, the warning is gone.

But, is this the right way of fixing this issue? And what is the difference between the second code and the third code? Does code 3 means that I have abandoned the first object?

Code: 2

import java.util.Scanner;

public class Ex {
    private Scanner input;

    public void sum() {
        input = new Scanner(System.in);
    }
}

Code: 3

import java.util.Scanner;

public class Ex {
    private Scanner input = new Scanner(System.in);

    public void sum() {
        input = new Scanner(System.in);
    }
}

Upvotes: 1

Views: 392

Answers (3)

Sathish
Sathish

Reputation: 5173

You are getting the warning because the scanner instance is never closed. Modify the code: 1 as below to eliminate the warning,

public void sum() {
    Scanner input = null;
    try {
        input  = new Scanner(System.in);
        // do operation
    } finally {
         input.close();
    }
}

Regarding code:2, declare any variable at Object level only when its required. i.e if it needs to be accessed by multiple member functions defined in the class.

To answer your question is this the right way of fixing this issue , and what is the difference between the second code and the third code ? Does code : 3 means that i have abandoned the first object ?

No, Code: 3 is not the right way way to fix the issue. And yes, code:3 creates a new instance of scanner inside the member function "sum" and the reference of the member variable input will point to the newly created scanner instance.

In summary, create a member variable (object level) only when its absolutely required, otherwise create a local variable - this will ensure that the objects get collected much earlier. (i.e. these objects will become eligible for GC when the method execution completes). Also, make sure that, call close() on almost all of the IO classes (stream classes) that we operate on.

Also, Note that if you close System.in, you won't be able to read from it again

Upvotes: 2

Codebender
Codebender

Reputation: 14438

  1. but , is this the right way of fixing this issue - No its not... The input is still not closed, only that Eclipse is not able to detect it anymore... The issue is still present...

That being said, it's not a good idea to close the Standard input System.in too (closing the Scanner object would close the underlying stream too as I understand)... Hence it would be better to leave it like that even though there is a warning...

  1. Yes, since in code 3 you have reinitialized input, you have abandoned the first object.

Upvotes: 5

JB Nizet
JB Nizet

Reputation: 691943

The presence of a warning is almost always a sign of a problem. But the absence of a warning doesn't mean there is no problem.

The first snippet warns you that you're not closing the Scanner object when you're done with it. The proper fix would be to close it. Not to make your code worse by using a field instead of a local variable, and still not closing the scanner when you're done with it. That will make the warning disappear, but not the problem. Variables should always have the narrowest possible scope.

That said, A Scanner opened with System.in as argument, although it implements Closeable (that's why you have the warning), should in fact not be closed, because that would close the underlying stream: System.in. File or Socket streams must be closed, but System.in should generally not. If you close it, the user won't be able to enter anything anymore to your program.

Upvotes: 5

Related Questions