关闭Scanner后Java程序报错,BPM转毫秒工具故障排查
问题分析与解决
问题根源
你遇到的“no line found”错误,核心原因是关闭Scanner时会连带关闭底层的System.in输入流:
- 在
ms_calc()中调用scanbpm.close()后,System.in被永久关闭。 - 随后你调用
main(null)再次执行ms_calc(),新创建的Scanner scanbpm = new Scanner(System.in)试图读取已经关闭的输入流,直接触发NoSuchElementException。 - 另外你的
get_user_int方法里的finally块每次都调用scan.nextLine(),如果用户输入有效整数后,nextInt()只会读取数字,剩下的换行符会被nextLine()消费,这个逻辑本身没问题,但配合输入流关闭的问题会直接引发报错。
修复方案
1. 避免递归调用main(null),改用循环结构
不要通过重复调用main方法实现程序循环,改用while循环控制程序的运行状态。
2. 只创建一次Scanner,全程复用
把Scanner的创建放在循环外部,直到程序结束时再关闭,避免重复关闭System.in输入流。
修改后的代码示例
import java.util.Scanner; public class BpmToMsConverter { public static void main(String[] args) { Scanner scanbpm = new Scanner(System.in); boolean keepRunning = true; while (keepRunning) { ms_calc(scanbpm); // 询问用户是否继续计算 System.out.println("是否继续计算?(输入y继续,其他键退出)"); String choice = scanbpm.nextLine().trim(); if (!choice.equalsIgnoreCase("y")) { keepRunning = false; } } scanbpm.close(); // 程序结束时统一关闭Scanner } public static void ms_calc(Scanner scanbpm) { System.out.println("What is your BPM?"); int bpm = get_user_int(scanbpm, 1, 2300); // BPM转毫秒计算逻辑 double mS1 = Math.round((bpm * 100.0) / 6) * 4; double mS2 = Math.round((bpm * 100.0) / 6) * 2; int mS1R = (int) mS1; int mS2R = (int) mS2; System.out.println("____________________________________"); System.out.println(); System.out.println("Whole : " + mS1R + " ms"); System.out.println(); System.out.println("1/2 : " + mS2R + " ms"); for (int X = 1; X < 9; X = X * 2) { double mS = Math.round((60000.00 / X) / bpm); int Y = X * 4; int mSR = (int) mS; System.out.println(); System.out.println("1/" + Y + " : " + mSR + " ms"); } System.out.println("____________________________________"); System.out.println(); } public static int get_user_int(Scanner scan, int min, int max) { int user_input = min - 1; boolean keep_asking = true; while (keep_asking || user_input < min || user_input > max) { try { user_input = scan.nextInt(); keep_asking = false; // 验证输入范围,不合法则重新提示 if (user_input < min || user_input > max) { System.out.println("输入超出范围,请输入" + min + "到" + max + "之间的整数"); keep_asking = true; } } catch (Exception e) { System.out.println("Invalid input. 请输入整数"); scan.nextLine(); // 消费无效输入的剩余内容 keep_asking = true; } } scan.nextLine(); // 消费输入整数后的换行符,避免影响后续输入 System.out.println(user_input); return user_input; } }
额外优化点
- 原计算逻辑中的
(bpm*100)/6改为(bpm * 100.0)/6,避免整数除法导致的精度丢失。 - 在
get_user_int中增加了范围验证的提示,让用户更清楚错误原因。 - 移除了
finally块中的scan.nextLine(),改为在有效输入后针对性消费换行符,避免不必要的输入干扰。
内容的提问来源于stack exchange,提问作者Rivera
相关产品推荐
相关产品推荐

