我的课程作业是编写一个程序,用户输入一组数值。如果用户输入的值不是数字,程序应该给用户2次正确输入数字的机会,在这两次机会之后,退出请求输入并打印到目前为止正确输入的所有值的总和
原样,我的代码不能正常工作。当输入第一个非数字时,程序执行一次catch块中的代码,在try块的开头打印“gimme input”行,然后立即执行catch中的代码再次阻止,无需等待用户输入另一个号码。
在仔细阅读我的教科书时,我注意到这一行:“NoSuchElementException是未被任何catch子句捕获。异常仍被抛出,直到它被另一个try块或main捕获方法终止。“
这很棒,因为现在至少我知道这是一个很好的理由,但我的教科书中没有关于这个怪癖的任何进一步信息,而且我无法通过StackOverflow找到任何可理解的答案或谷歌。所以我的问题是两部分:
a)为了这项任务,我该如何解决这个问题?
b)究竟是什么意思是异常没有被catch子句捕获?这不是捕捉条款的存在吗?我确实想要一个解决我的任务的方法,但我也想了解为什么这就是它的方式,如果可能的话。
感谢您的帮助!
import java.util.InputMismatchException;
import java.util.NoSuchElementException;
import java.util.ArrayList;
import java.util.Scanner;
public class NotANumber {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
System.out.println("This program computes the sum of any number of real numbers. When you are done entering values, enter something other than a real number twice in a row.\n");
ArrayList<Double> numbers = new ArrayList<Double>();
int count = 0;
while (count < 2) {
try {
System.out.println("Please enter a floating point number: ");
double newNumber = in.nextDouble();
numbers.add(newNumber);
count = 0;
}
catch (NoSuchElementException exception) {
System.out.println("The value entered was not correctly specified. All values must be integers or floating point values.");
count++;
}
}
if (!numbers.isEmpty()) {
double sum = 0;
for (Double each : numbers) {
sum = sum + each;
}
System.out.println("The sum is " + sum);
}
else {
System.out.println("There is no sum as no correctly specified values were entered.");
}
}
}
答案 0 :(得分:4)
现在,忘记捕获异常(这不是你想要做的!)。你想要做的是在调用s.nextDouble()之前添加如:s.hasDouble()之类的调用。
你不想捕获该异常的原因是因为它是一个RuntimeException,用于表示程序员错误,你应该修复它。
简单的建议是不要捕获编译器没有告诉你捕获的异常,而是如果其中一个被抛出,你需要知道你需要对代码进行的更改,以便不会发生异常。< / p>
对于异常,编译器会告诉您必须处理它们,例如:
try
{
foo();
}
catch(final IOException ex)
{
// do something smarter here!
ex.printStackTrace();
}
在该代码中,foo()被声明为:
public void foo()
throws IOException
{
// ... code ...
}
IOException是一个经过检查的异常(RuntimeException,也称为未经检查的异常,不应该被捕获,必须检查已检查的异常......除了catch之外你还可以做其他事情,但现在不要担心这些)。 / p>
所以,很长的答案很简短,在调用s.hasXXX()
之前调用s.nextXXX()
不会发生异常。
答案 1 :(得分:1)
你错了:如果输入用完,Scanner.nextDouble
会抛出一个NoSuchElementException
,这在标准输入中不太可能发生(它会阻塞)。不正确的值将产生InputMismatchException
。
但我的猜测是,nextDouble
在失败时不会从流中删除违规值。在恢复读取之前,您需要“清除”捕获中的输入。
答案 2 :(得分:1)
@TofuBear声明:
简单的建议是不要捕获编译器没有告诉你捕获的异常,而是如果其中一个被抛出,你需要知道你需要对代码进行的更改,以便不会发生异常。< / p>
我认为这是一种过度简化。
确实,声明为已检查异常的异常必须在方法签名中被捕获或声明为抛出。
你也不必捕捉未经检查的异常,事实上你应该仔细考虑是否明智地捕获未经检查的异常。 (例如,您应该考虑是否在您期望的点以及您期望的原因引发异常。)
然而,在某些情况下,显然有必要抓住它们。例如:
try {
System.out.println("Enter a lucky number!");
String input = // get string from user
int number = Integer.parseInt(input);
...
} catch (NumberFormatException ex) {
System.err.println("Bad luck! You entered an invalid number");
}
如果您没有抓住NumberFormatException
...这是未经检查的例外...那么您就无法打印出友好的消息,并询问用户再试一次。
简而言之,未经检查的异常并不总是意味着程序员错误。
一些标准的可以表示来自用户或客户端的错误输入(例如NumberFormatException,IllegalArgumentException,ArithmeticException等),或者可以指示特定应用程序可以从中恢复或至少尝试诊断的内容。
我遇到过第三方库,设计人员厌恶检查异常,并声明所有库异常都未经检查。 (设计错误的IMO,但它发生了......)
因此,你不应该抓住未经检查的例外的一揽子声明显然是错误的建议。
然而,@ TofuBear的第二部分建议是有效的。 (通常)更好的做法是进行测试以防止发生预期的异常,而不是执行操作并捕获异常。 (代码通常更简单,通常更有效......尽管有反例。)
在这种情况下,如果您在hasNextDouble()
之前调用并测试nextDouble()
,则可以避免尝试使用try / catch处理错误的情况。
答案 3 :(得分:0)
for (ListIterator<Double> iter = numbers.listIterator(); iter.hasNext(); ) {
if(iter.hasNext()) { // this return false in case of NoSuchElementException
// do your stuff here
}
}
答案 4 :(得分:-2)
您必须更改导入。
代替
import java.util.NoSuchElementException;
使用
import org.openqa.selenium.NoSuchElementException;