生死对象的解释

时间:2015-06-06 10:24:18

标签: java

以下代码向我发出警告:“资源泄漏,输入永不关闭”

代码:1

import java.util.Scanner;

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

我发现在类级别声明input变量可以解决问题,警告就消失了。

但是,这是解决这个问题的正确方法吗?第二个代码和第三个代码之间有什么区别?代码3是否意味着我放弃了第一个对象?

代码:2

import java.util.Scanner;

public class Ex {
    private Scanner input;

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

代码:3

import java.util.Scanner;

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

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

3 个答案:

答案 0 :(得分:5)

警告的存在几乎总是一个问题的迹象。但是没有警告并不意味着没有问题。

第一个片段警告您,当您完成它时,您没有关闭Scanner对象。正确的解决方法是关闭它。不要通过使用字段而不是局部变量来使代码变得更糟,并且在完成扫描时仍然不关闭扫描程序。这将使警告消失,但不是问题。变量应始终具有尽可能窄的范围。

那说,A ScannerSystem.in作为参数打开,虽然它实现了Closeable(这就是你有警告的原因),实际上应该不会被关闭,因为那会关闭底层流:System.in。必须关闭文件或套接字流,但通常不应该System.in。如果您关闭它,用户将无法再向您的程序输入任何内容。

答案 1 :(得分:5)

  1. 但是,这是解决此问题的正确方法 - 不是没有......输入仍未关闭,只是Eclipse无法再检测到它...问题还在......
  2. 话虽如此,关闭标准输入System.in也不是一个好主意(关闭Scanner对象也会关闭基础流,因为我理解)...因此它会更好即使有警告就这样离开......

    1. 是的,因为在代码3中您已重新初始化input,您已放弃第一个对象。

答案 2 :(得分:2)

您收到警告,因为扫描仪实例从未关闭。修改代码:1,如下所示消除警告,

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

关于代码:2,仅在需要时在Object级别声明任何变量。即如果它需要由类中定义的多个成员函数访问。

回答你的问题这是解决这个问题的正确方法,第二个代码和第三个代码有什么区别?代码:3表示我放弃了第一个对象吗?

不,代码:3不是解决问题的正确方法。是的,代码:3在成员函数“sum”中创建一个新的scanner实例,成员变量输入的引用将指向新创建的扫描程序实例。

总之,仅在绝对需要时创建成员变量(对象级别),否则创建局部变量 - 这将确保更早收集对象。 (即,当方法执行完成时,这些对象将符合GC的条件)。另外,请确保在我们操作的几乎所有IO类(流类)上调用close()。

另请注意,如果您关闭System.in,则无法再次读取