如何捕获NoSuchElementException?

时间:2011-04-15 03:37:41

标签: java exception-handling

我的课程作业是编写一个程序,用户输入一组数值。如果用户输入的值不是数字,程序应该给用户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.");
        }

    }
}

5 个答案:

答案 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)

围绕try..catch围绕你的陈述是一个好主意,当你不知道在真实场景中会发生什么。但我有替代解决方案,大多数时候我们都知道这个异常提升所以你可以使用如下的实现迭代器来避免它...

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;