Java计算图形面积周长时NoSuchElementException异常修复方案
问题描述
我正在编写一个用于计算圆形与矩形面积、周长的程序,圆形的半径、矩形的宽和长均需从用户输入获取。输入半径参数后,控制台抛出如下异常:
Exception in thread "main" java.util.NoSuchElementException at...
项目包结构说明:
Main.java存放于main包Circle.java与Rectangle.java存放于shapes包
问题相关代码
Main.java
package main; import shapes.Circle; import shapes.Rectangle; //import java.util.Scanner; public class Main { public static void main(String[] args) { Circle cir = new Circle(); Rectangle rec = new Rectangle(); cir.printArea(); cir.printPerimeter(); rec.printArea(); rec.printPerimeter(); } }
Circle.java
package shapes; import java.util.Scanner; public class Circle { final double PI = 3.14; double radius; double area, perimeter; public Circle(double radius) { this.radius = radius; area = PI*radius*radius; perimeter = 2*PI*radius; } public Circle() { System.out.print("radius = "); Scanner scan = new Scanner(System.in); radius = scan.nextDouble(); scan.close(); area = PI*radius*radius; perimeter = 2*PI*radius; } public void printArea() { System.out.println("Area of circle = " + area); } public void printPerimeter() { System.out.println("Perimeter of circle = " + perimeter); } }
Rectangle.java
package shapes; import java.util.Scanner; public class Rectangle { public double length, width; double area, perimeter; public Rectangle(double length, double width) { this.length = length; this.width = width; area = length * width; perimeter = (length + width) * 2; } public Rectangle() { Scanner scan = new Scanner(System.in); System.out.print("width = "); width = scan.nextDouble(); System.out.print("length = "); length = scan.nextDouble(); scan.close(); area = length * width; perimeter = (length + width) * 2; } public void printArea() { System.out.println("Area of rectangle = " + area); } public void printPerimeter() { System.out.println("Perimeter of rectangle = " + perimeter); } }
异常原因
这个异常的根源是错误关闭了绑定标准输入流System.in的Scanner对象。
Java中所有基于System.in创建的Scanner,共用同一个底层输入流。你在Circle类的无参构造里读完半径就调用scan.close(),这一步会直接把整个System.in流关掉,不是只释放当前Scanner的资源。等后面执行new Rectangle()时,Rectangle构造方法里新创建的Scanner尝试从已经关闭的输入流读取数据,就会抛出NoSuchElementException。
修复方案
核心原则:绑定System.in的Scanner全局只创建一个,不要在局部业务逻辑里随意关闭。
- 把所有用户输入逻辑从
Circle、Rectangle类中移除,统一放到Main类的主方法中处理:全局只创建一个Scanner实例,依次读取圆形半径、矩形宽和长,再把读到的参数传入两个类的有参构造方法创建实例。 - 所有输入全部读取完成后再统一关闭Scanner,也可以不手动关闭——程序退出时JVM会自动回收相关资源,不会产生资源泄漏。
- 两个形状类可以直接删掉包含输入逻辑的无参构造,只保留带参数的构造方法、面积周长计算和打印方法即可。
修复后的Main.java代码参考:
package main; import shapes.Circle; import shapes.Rectangle; import java.util.Scanner; public class Main { public static void main(String[] args) { // 全局唯一的Scanner实例,绑定标准输入 Scanner scan = new Scanner(System.in); System.out.print("radius = "); double radius = scan.nextDouble(); Circle cir = new Circle(radius); System.out.print("width = "); double width = scan.nextDouble(); System.out.print("length = "); double length = scan.nextDouble(); Rectangle rec = new Rectangle(length, width); // 所有输入读取完成后再关闭Scanner scan.close(); cir.printArea(); cir.printPerimeter(); rec.printArea(); rec.printPerimeter(); } }
内容的提问来源于stack exchange,提问作者Becker
相关产品推荐
相关产品推荐

