如何正确关闭方法内的Scanner类?

时间:2014-11-15 22:47:45

标签: java

我有这个代码调用一个方法来检查一个数字是否是一定的长度,如果没有,则应该由用户重新引入一个新的数字。

问题在于,我无法找到关闭Scanner类的正确方法,以防止资源泄漏。

到目前为止,这是代码。

    public static void setIdentification(Person p, int dni) {
    Scanner input = new Scanner (System.in);
    String lengthChecker = Integer.toString(dni);
    if (lengthChecker.length() < 1 || lengthChecker.length() > 8) {
        int dni1; 
        do{
            System.out.println("The ID number isn't valid. Please, introduce a valid number: ");
            dni1 = input.nextInt();
            lengthChecker = Integer.toString(dni1);
            } while (lengthChecker.length() > 8 || lengthChecker.length() < 1 );
        p.dni = dni1;
    } else {
        p.dni = dni;
    }
}
public static void main(String[] args) {
    Scanner input1 = new Scanner (System.in);
    int dni = input1.nextInt();
    Person person1 = new Person();
    setIdentification(person1, dni);
}

我尝试在许多不同的位置设置input.close();,但我总是遇到运行时错误。

可能有一百万种方法可以优化此代码,但现在我真的很好奇如何让这些扫描仪关闭。

2 个答案:

答案 0 :(得分:3)

@Jules是正确的。在这种情况下,关闭Scanner既不必要也不可取。

但假设你这样做了,那么推荐的方法是:

try (Scanner input1 = new Scanner (System.in)) {
    int dni = input1.nextInt();
    Person person1 = new Person();
    setIdentification(input1, person1, dni);
}

...注意您必须更改setIdentification方法,以便它不会尝试打开自己的扫描仪。为同一输入流创建多个扫描仪是一个错误。实际上,你的代码中存在 错误。

这适用于Java 7及更高版本。 (在大多数情况下,您不应该为旧版本的Java编写新代码.Android是一个例外,因为Java 7扩展的支持最近才在Android工具链中可用。


那么为什么不能在同一个流上打开和关闭多个扫描仪呢?有两个原因:

  1. 关闭扫描仪时,会自动关闭基础流。这意味着如果您然后尝试在流上打开/使用另一个扫描程序,则当您尝试从已关闭的流中读取时,它将失败。流无法重新打开

  2. 即使您不关闭扫描仪/流,在流上创建第二台扫描仪也可能会导致问题。扫描仪必须提前读取以确定令牌边界的位置。然后它将任何预读字符保留在内部缓冲区中。每个扫描仪都有自己的缓冲区。因此,如果您有两个或更多扫描仪用于相同的流,并交错使用它们,则一个扫描仪可能会“抓住”#34;另一台扫描仪需要的字符。

答案 1 :(得分:2)

关闭扫描仪将关闭使用它创建的输入流。在您的情况下,这是System.in。此流是一种特殊情况:它在程序开始运行之前由环境打开,因此通常不应该由程序关闭。

在这种情况下,可以不关闭扫描仪。让垃圾收集器处理它。