提问人:simo 提问时间:11/15/2022 更新时间:11/15/2022 访问量:119
扫描仪在方法中从未关闭,但我认为它实际上会在每次方法结束时关闭?
Scanner is never closed in method, but I think it does actually close every time the method ends?
问:
public static void maxintRecursive(int max) {
// create scanner
Scanner in = new Scanner(System.in);
// asks user for integer input
int a = in.nextInt();
// checks if integer input satisfies exit condition, closes scanner, prints max and returns
if (a <= 0) {
in.close();
System.out.println("Max int is: " + max);
return;
}
// checks if input is greater than previous max registered int
if (a > max) {
max = a;
}
// calls itself again
maxintRecursive(max);
}
我可以成功编译并运行它,但在第 3 行它下划线“in”表示它永远不会关闭 但是,此方法会不断调用自身,直到达到退出条件 (<=0) ,在此条件下,扫描程序实际上会关闭
这是一个错误吗?它实际上永远不会关闭并且我遇到内存泄漏吗?
我应该从主方法中传递扫描仪,还是相同?
此递归方法要求用户输入整数,并在用户输入 0 或更少时返回收到的最大整数
我在方法内部创建了一个扫描程序,并在递归方法达到其退出条件时将其关闭
我预计扫描程序会在退出条件下被我的代码关闭,但 VS Code 说它永远不会关闭
答:
每次调用方法时,它都会创建自己的局部变量。例如,如果您有像
void foo(int n) {
int x = n + 1;
if (x < 2)
foo(x);
}
然后你像那样调用它,在执行时它将有自己的两个局部变量(方法参数)和(在方法主体中声明)。
然后,当您递归调用时,该调用将创建另一组局部变量,这些变量将保存值。foo(0);
n=0
x = n+1 = 0+1 = 1
foo(x);
foo(1)
n
x
n=1
x=2
同样,在您的示例中,每次调用 method 时,它都会创建自己的单独对象。因此,如果您调用方法 N 次,则会创建 N 个 Scanner
对象(所有这些对象都从 中读取)。即使调用方法处理,它也只会关闭由该递归调用创建的 Scanner。在以前的方法调用中创建的其他扫描程序永远不会关闭。maxintRecursive
Scanner in = new Scanner(...)
System.in
in.close();
if (a <= 0)
可能的解决方案还可以在方法末尾添加(在递归调用之后),这将确保每个方法都将关闭自己的 Scanner。in.close();
但首选的解决方案是首先防止创建如此多的扫描仪。相反,在方法中创建一个并将其作为参数传递给递归方法。由于它将被传递,因此 Java 不会强制您在方法本身中关闭该扫描程序,而是在创建它的范围内(主方法)中关闭该扫描程序。main
为此,您需要通过修改其声明(例如)来让 Scanner 接受其参数maxintRecursive
public static void maxintRecursive(int max, Scanner in) {
//...
}
这样,您现在需要的只是类似的东西
public static main(String[] args){
Scanner scanner = new Scanner(System.in);
maxintRecursive(-1, scanner);
scanner.close();
}
顺便说一句,我们避免创建在我们自己的方法中处理的 Scanner 的另一个原因是,通过该方法关闭此类 Scanner 也会关闭 。这意味着当您尝试再次调用您的方法时,它将创建 Scanner,它将尝试从已经关闭的 .同样,在这种情况下,首选解决方案是将扫描仪处理 System.in 作为方法参数传递。System.in
System.in
System.in
评论