Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to catch a NoSuchElementException?

My class assignment is to write a program that has the user input a set of numerical values. If the user enters a value that is not a number, the program is supposed to give the user 2 second chances to enter a number correctly, and after those two chances, quit asking for input and print the sum of all values entered correctly so far.

As is, my code doesn't work quite right. When the first non-number is entered, the program executes the code in the catch block once, prints the "gimme input" line at the beginning of the try block but then immediately executes the code in the catch block again without waiting for the user to enter another number.

While perusing my textbook for clues, I noticed this line: "A NoSuchElementException is not caught by any of the catch clauses. The exception remains thrown until it is caught by another try block or the main method terminates."

Which is great, because now at least I know there's a good reason this is happening, but my textbook doesn't contain any further information on this quirk, and I haven't been able to find any understandable answers via StackOverflow or Google. So my question is two part:

a) How should I get around this for the purposes of this assignment?

b) What exactly does it mean that the exception is not caught by a catch clause? Isn't that what catch clauses exist for? I do want a solution to my assignment, but I also want to understand why this is the way it is, if possible.

Thanks for any help!

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.");
        }

    }
}
like image 473
ellriley Avatar asked Apr 15 '11 03:04

ellriley


1 Answers

For now, forget about catching the exception (it isn't what you want to do!). What you want to do is add calls like: s.hasDouble() before calling s.nextDouble().

The reason you don't want to catch that exception is because it is a RuntimeException which is meant to be used to indicate a programmer mistake, one that you should fix.

The simple advice is don't catch exceptions that the compiler doesn't tell you to catch, instead if one of them is thrown figure out the change you need to make to your code so that exception doesn't happen.

For exceptions the compiler tells you that you must deal with them you do something like:

try
{
    foo();
}
catch(final IOException ex)
{
    // do something smarter here!
    ex.printStackTrace();
}

In that code, foo() is declared something like:

public void foo() 
    throws IOException 
{
   // ... code ...
}

IOException is a checked exception (RuntimeException, also called unchecked exceptions, should not be caught, checked exceptions must be caught... well you can do other things beyond catch, but for now don't worry about those).

So, long answer short, make the exception not happen by calling s.hasXXX() before calling s.nextXXX().

like image 68
TofuBeer Avatar answered Oct 05 '22 06:10

TofuBeer