Java——关闭扫描器和资源泄漏

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/23621668/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-14 00:21:02  来源:igfitidea点击:

Java -- Closing Scanner and Resource Leak

javaeclipsejava.util.scanner

提问by SuperCow

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 Scannerobject Eclipse warns me that:

我正在学习 Java 并从事一些有趣的项目。我遇到的一个问题是,当我使用Scanner对象时,Eclipse 会警告我:

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.

所以,我scan.close();在我的代码末尾添加了一个并处理警告。

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.

问题出现了,因为我在同一个包中有其他类也使用扫描仪对象,并且 Eclipse 告诉我分别关闭这些类中的扫描仪。但是,当我这样做时,它似乎关闭了所有扫描仪对象,并且在运行时出现错误。

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 scanTestclass and the do loop in test2is entered again an error occurs at the line test = scan.nextInt();

scanTest班级中关闭扫描仪并test2再次进入do 循环后,该行发生错误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.

我尝试将扫描仪对象的创建移动到 do 循环中,只是为了每次都创建一个新对象,但错误仍然发生。

Not sure why this is happening or how I can make sure all my I/O objects are closed out without running into problems.

不知道为什么会发生这种情况,或者我如何确保我的所有 I/O 对象都被关闭而不会遇到问题。

One post I came across mentioned that when System.inis 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)?

我遇到的一篇帖子提到System.in关闭时我无法重新打开。如果是这种情况,我是否只需要确保在程序的最后关闭带有 System.in 的扫描仪对象并@suppress 其他类中的所有其他扫描仪警告?或者这仍然会使所有这些扫描仪对象保持打开状态(坏)?

回答by Edwin Buck

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.

其次,当您关闭流包装器时,默认实现是关闭它包装的流。这意味着您第一次关闭扫描仪(如其所写)时,是的,您关闭了 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.

一般来说,如果他们打算再次从 System.in 读取,则希望避免关闭 System.in。解决此问题的最佳方法取决于您的程序。

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.

可以将 System.in 中的信息复制到某种缓冲区中,然后扫描缓冲区。人们可能不会关闭扫描仪,而是在其他位置重复使用它。甚至可以取消对 Scanner 的引用以进行垃圾收集,并在 System.in 上创建多个新的 Scanner。

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).

这些解决方案并不都是等价的,有些被认为比其他解决方案要好得多;但是,这一切都取决于调用程序。尝试一些,如果遇到问题,请打开一个新的 StackOverflow 问题,在其中显示代码的相关部分、问题的描述、示例输入和错误的输出(以及所需的输出)。

Good luck.

祝你好运。

回答by Scary Wombat

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)

是的,当您关闭扫描仪时,您将关闭底层流(在本例中为 System.in)。为了避免这种情况,要么创建一个所有类都可以使用的扫描仪的全局变量,要么有一个用于关闭扫描仪的中心点(就在程序退出之前是理想的)

回答by TheTNTwither James

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.

*scanner name goes here*.close();为您的每台扫描仪放置。如果它们都具有相同的名称,则更改与其他扫描仪不同的那些。