递归方法中Scanner被提示未关闭,但已在终止条件关闭的问题
递归方法中Scanner相关问题解答
先贴出你的代码:
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 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 if (a > max) { max = a; } // recursive call maxintRecursive(max); }
下面逐个解答你的问题:
1. 这是IDE误报吗?
属于静态分析工具的误报。VS Code的代码检查无法追踪递归的执行流程,它只看到每次进入方法都会新建Scanner,而大部分递归分支(未触发终止条件的分支)里没有写close(),就直接标记“从未关闭”。但实际运行时,只有最后一次递归会触发关闭逻辑——不过这里还有个更关键的问题:前面所有递归层级创建的Scanner都没机会关闭。
2. 存在Scanner未关闭导致的内存泄漏吗?
不是内存泄漏(Java的垃圾回收会处理Scanner对象),但会造成IO资源泄漏(文件描述符泄漏)。每次递归都会创建绑定System.in的Scanner,只有最后一个被关闭,之前的Scanner都持有System.in的底层资源引用,无法及时释放。虽然程序终止后系统会回收资源,但如果递归次数多,可能在运行时耗尽系统的文件描述符,导致其他IO操作异常。
另外还有个隐藏问题:关闭最后一个Scanner时会同时关闭System.in,但前面递归里的Scanner还绑定着已关闭的输入流,不过这在你的程序终止逻辑下影响不大。
3. 从main方法传入Scanner,效果会不同吗?
这是更合理的写法,效果完全不同:
- 全程复用同一个Scanner实例,不会重复创建,从根源避免了资源泄漏。
- IDE不会再提示未关闭的问题,因为静态检查能追踪到这个Scanner会在main方法里被关闭。
- 代码职责更清晰:IO资源由上层(main)统一管理,递归方法只负责业务逻辑。
修改后的示例代码:
public static void main(String[] args) { Scanner in = new Scanner(System.in); maxintRecursive(0, in); in.close(); } public static void maxintRecursive(int max, Scanner in) { int a = in.nextInt(); if (a <= 0) { System.out.println("Max int is: " + max); return; } if (a > max) { max = a; } maxintRecursive(max, in); }
内容的提问来源于stack exchange,提问作者simo
相关产品推荐
相关产品推荐

