Java立方体计算程序第二、三实例运行时抛出NoSuchElementException异常求助
问题排查与解决方案
嘿,我一眼就找到你这个NoSuchElementException的根源啦!
为什么会抛出这个异常?
你在getLength()方法里犯了一个常见的错误:每次调用这个方法时,你都新建了一个Scanner实例,并且在方法结束时调用sc.close()。这里的关键是:当你关闭Scanner的时候,它会自动关闭底层关联的System.in输入流——而System.in是全局唯一的,一旦被关闭就再也无法重新打开。
所以第一次创建cube1时,一切正常;但到cube2和cube3调用getLength()时,新的Scanner尝试读取已经被关闭的System.in,自然就抛出NoSuchElementException了。
怎么修复?
我给你推荐两种可行的修复方案,其中第一种是最规范的:
方案1:全局共享一个Scanner(推荐)
创建一个唯一的Scanner实例,在整个程序中复用它,只在程序结束前关闭一次。这样就不会出现关闭System.in的问题了。修改后的代码如下:
import java.util.InputMismatchException; import java.util.Scanner; import java.io.*; public class Cube { // 遵循Java规范,类名首字母大写 private double side; // 定义一个静态Scanner,所有实例共享 private static Scanner sc = new Scanner(System.in); public double getLength(){ while(true){ try{ System.out.println("Please enter an integer: "); side = sc.nextDouble(); break; } catch(InputMismatchException e){ // 变量名更有意义 System.err.println("\nWrong character - please enter a valid number!"); sc.next(); // 跳过非法输入,避免死循环 continue; } } // 不要在这里关闭Scanner! return side; } /** * 计算立方体的表面积 * @return 表面积数值 */ public double calculateSurfaceArea(){ return 6 * side * side; } /** * 计算立方体的体积 * @return 体积数值 */ public double calculateVolume(){ return side * side * side; } public static void main(String args[]) throws IOException { Cube cube1 = new Cube(); System.out.println("\nSide length of cube1 is " + cube1.getLength()); System.out.println("Surface Area of cube1 is " + cube1.calculateSurfaceArea()); System.out.println("Volume of cube1 is " + cube1.calculateVolume()); Cube cube2 = new Cube(); System.out.println("\nSide length of cube2 is " + cube2.getLength()); System.out.println("Surface Area of cube2 is " + cube2.calculateSurfaceArea()); System.out.println("Volume of cube2 is " + cube2.calculateVolume()); Cube cube3 = new Cube(); System.out.println("\nSide length of cube3 is " + cube3.getLength()); System.out.println("Surface Area of cube3 is " + cube3.calculateSurfaceArea()); System.out.println("Volume of cube3 is " + cube3.calculateVolume()); // 程序结束前,统一关闭Scanner sc.close(); } }
方案2:不在方法内关闭Scanner(临时方案)
如果你不想调整全局结构,也可以直接删除getLength()里的sc.close();语句。这样每个Scanner实例都关联到System.in,虽然不会抛出异常,但会创建多个冗余的Scanner对象,存在潜在的资源泄漏风险,所以不推荐长期使用这个方案。
额外的编码小建议
最后给你提几个Java编码规范的小细节,让代码更专业:
- 类名必须首字母大写(比如把
cube改成Cube) - 异常变量名尽量有意义(比如把
a改成e或者inputException) - 方法注释使用Javadoc格式(
/** ... */),方便生成文档和他人阅读
内容的提问来源于stack exchange,提问作者Aureliux
相关产品推荐
相关产品推荐

