使用Java Scanner的nextInt()时遇NoSuchElementException及无限循环问题
终端版战舰游戏shipLocations方法二次调用异常问题解决
问题根源
你的核心问题出在重复创建并关闭Scanner实例:
- 每次调用
shipLocations方法时,都新建Scanner input = new Scanner(System.in),并且在方法末尾调用input.close()。关闭Scanner会连带关闭底层的System.in输入流,第二次调用方法时,新建的Scanner已经无法从已关闭的System.in读取数据,导致hasNextInt()永远返回false,或者直接抛出NoSuchElementException。 - 初始化坐标为6时,会进入无效坐标循环,但输入流已关闭后
hasNextInt()一直为false,coordinate1和coordinate2始终是6,循环条件invalidCoords永远为true,触发无限循环;设为0时,第一次调用后关闭输入流,第二次调用时无法读取输入,直接抛出异常。
解决方案
- 复用同一个Scanner实例:在main方法中仅创建一次Scanner,作为参数传递给
shipLocations方法,统一在main方法结束前关闭它,避免破坏System.in输入流。 - 优化输入校验逻辑:用单一循环处理所有无效输入场景,同时清理输入流中残留的换行符,避免干扰后续读取。
修改后的代码
import java.util.Scanner; public class battleship { public static void main(String[] args){ Scanner input = new Scanner(System.in); // 仅创建一次Scanner实例 System.out.println("Hello Mortals, Welcome to Battleship!"); System.out.println("PLAYER 1, Enter your ships' coordinates."); int[] coordinate1 = shipLocations(1, input); int[] coordinate2 = shipLocations(2, input); // int[] coordinate3 = shipLocations(3, input); // int[] coordinate4 = shipLocations(4, input); // int[] coordinate5 = shipLocations(5, input); input.close(); // 统一在程序结束前关闭Scanner } public static int[] shipLocations(int shipNumber, Scanner input){ int coordinate1; int coordinate2; int[] coordinates = new int[2]; boolean invalidCoords; do { invalidCoords = false; System.out.println("Enter Ship " + shipNumber + " location: "); // 校验是否输入了两个有效整数 if(!input.hasNextInt()){ System.out.println("输入无效,请输入两个整数坐标!"); input.nextLine(); // 清理当前行的无效输入 invalidCoords = true; continue; } coordinate1 = input.nextInt(); if(!input.hasNextInt()){ System.out.println("输入无效,请输入两个整数坐标!"); input.nextLine(); // 清理无效输入 invalidCoords = true; continue; } coordinate2 = input.nextInt(); input.nextLine(); // 清理输入后的换行符,避免干扰后续读取 // 校验坐标范围(0-4) if(coordinate1 < 0 || coordinate1 > 4 || coordinate2 < 0 || coordinate2 > 4){ System.out.println("Invalid Coordinates. Choose different Coordinates."); invalidCoords = true; } else { coordinates[0] = coordinate1; coordinates[1] = coordinate2; } } while(invalidCoords); return coordinates; } }
关键修改点说明
- 移除方法内的Scanner创建和关闭逻辑,改为外部传入实例,保护
System.in输入流不被提前关闭。 - 重构校验逻辑,用单一循环处理非整数输入、坐标超范围等所有无效场景,避免分支混乱。
- 每次读取整数后调用
input.nextLine()清理换行符,防止残留的空白字符影响后续输入判断。 - 增加坐标下限校验(不能小于0),让逻辑更严谨。
内容的提问来源于stack exchange,提问作者Dylan Wangrud
相关产品推荐
相关产品推荐

