以下代码向我发出警告:“资源泄漏,输入永不关闭”:
代码: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);
}
}
答案 0 :(得分:5)
警告的存在几乎总是一个问题的迹象。但是没有警告并不意味着没有问题。
第一个片段警告您,当您完成它时,您没有关闭Scanner
对象。正确的解决方法是关闭它。不要通过使用字段而不是局部变量来使代码变得更糟,并且在完成扫描时仍然不关闭扫描程序。这将使警告消失,但不是问题。变量应始终具有尽可能窄的范围。
那说,A Scanner
以System.in
作为参数打开,虽然它实现了Closeable
(这就是你有警告的原因),实际上应该不会被关闭,因为那会关闭底层流:System.in。必须关闭文件或套接字流,但通常不应该System.in
。如果您关闭它,用户将无法再向您的程序输入任何内容。
答案 1 :(得分:5)
话虽如此,关闭标准输入System.in
也不是一个好主意(关闭Scanner
对象也会关闭基础流,因为我理解)...因此它会更好即使有警告就这样离开......
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,则无法再次读取