Eclipse提示已调用close()的Scanner从未关闭的问题咨询
问题描述
编写基于for循环实现的3次核发射密码校验逻辑Java代码,实际运行效果符合预期,但Eclipse弹出警告,提示初始化的Scanner资源从未关闭,即使代码末尾已经显式调用scan.close()方法。
编写逻辑几乎完全一致、基于do-while循环实现的同功能代码,不会触发前述Scanner未关闭的警告。
for循环实现版本(触发资源未关闭警告)
package test; import java.util.Scanner; public class Nukes_for { public static void main(String[] args) { Scanner scan = new Scanner(System.in); String code = "password123"; String input; int i; for (i=0; i < 3; i++) { System.out.print("Enter Nuclear Launch code: "); input = scan.nextLine(); System.out.println("Launch code: " + input); boolean passcheck = code.equals(input); if (passcheck == true) { System.out.println("Accepted"); System.out.println("Missiles away"); break; } else if (input.equals("exit")) { System.out.println("Exiting"); break; } else { System.out.println("Rejected"); } } if (i > 2) { System.out.println("Maximum tries exceeded"); System.out.println("Exiting"); } scan.close(); } }
do-while循环实现版本(无警告)
package test; import java.util.Scanner; public class Nukes_do_while { public static void main(String[] args) { Scanner scan = new Scanner(System.in); String code = "password123"; String input; int counter = 0; boolean passcheck; do { System.out.print("Enter Nuclear Launch code: "); input = scan.nextLine(); System.out.println("Launch code: " + input); passcheck = code.equals(input); counter++; if (passcheck == true) { System.out.println("Accepted"); System.out.println("Missiles away"); } else if (counter > 2) { System.out.println("Maximum tries exceeded"); System.out.println("Exiting"); break; } else if (input.equals("exit")) { System.out.println("Exiting"); break; } else { System.out.println("Rejected"); } } while (passcheck==false); scan.close(); } }
原因解释
这个警告是Eclipse内置静态代码分析规则的误判,代码本身不存在实际的资源泄漏问题,核心原因是Eclipse的资源泄漏检测逻辑对不同循环结构的分支覆盖判断精度存在差异:
- 两段代码实际运行时,只要没有抛出未捕获的异常,
scan.close()都会被正常执行,不存在资源未释放的问题。 - 针对for循环版本,Eclipse的静态分析器在追踪循环内的
break跳转、循环变量i的取值分支时,没有正确推导到「所有跳出循环的执行路径最终都会走到方法末尾的scan.close()」,错误判定存在跳过close方法的执行分支,因此弹出警告。 - 针对do-while循环版本,静态分析器可以顺利完成全分支路径追踪,确认所有跳出循环的路径都会顺序执行到循环外的
scan.close(),因此不会触发警告。
补充说明:Java 7及以上版本推荐使用
try-with-resources语法处理这类需要手动关闭的资源,从语法层面强制保证资源释放,彻底避免这类静态分析误判,示例写法如下:public static void main(String[] args) { // 资源初始化放在try后的括号内 try (Scanner scan = new Scanner(System.in)) { String code = "password123"; String input; int i; // 所有使用scan的业务逻辑写在当前代码块内 for (i=0; i < 3; i++) { // 原有业务逻辑保持不变 } } // 代码块执行结束后scan会被自动关闭,无需手动调用close() }
内容的提问来源于stack exchange,提问作者Karan Vess
相关产品推荐
相关产品推荐

