2

I am working on teaching myself java and while working on a code using classes I ran into this error

Exception in thread "main" java.util.NoSuchElementException
    at java.util.Scanner.throwFor(Unknown Source)
    at java.util.Scanner.next(Unknown Source)
    at java.util.Scanner.nextDouble(Unknown Source)
    at StateCalculator.getOperand(StateCalculator.java:29)
    at StateCalculator.main(StateCalculator.java:77)

Below is my code:

import java.util.Scanner;


public class StateCalculator {
    private double currentValue = 0;

    //Initialize to 0
    public StateCalculator() {
    }

    public static int displayMenu() {
        Scanner keyboard = new Scanner(System.in);
        int menuChoice = 0;

        do {
            System.out.print("Menu\n 1. Add\n 2. Subtract\n 3. Multiply\n 4. Divide\n 5.Clear\n 6. Quit\n What would you like to do?: ");
            menuChoice = keyboard.nextInt();
        } while(menuChoice < 1 || menuChoice > 6);

        keyboard.close();
        return menuChoice;
    }

    public static double getOperand(String prompt) {
        Scanner input = new Scanner(System.in);
        double operand = 0;

        System.out.print(prompt);
        operand = input.nextDouble();

        input.close();
        return operand;
    }

    public double getCurrentValue() {
        return currentValue;
    }

    public void add(double operand) {
        currentValue += operand;
    }

    public void subtract(double operand) {
        currentValue -= operand;
    }

    public void multiply(double operand) {
        currentValue *= operand;
    }

    public void divide(double operand) {
        if(operand == 0) {
            currentValue = Double.NaN;
        }
        else {
            currentValue /= operand;
        }
    }

    public void clear() {
        currentValue = 0;
    }


    public static void main(String[] args) {
        Scanner keyboard = new Scanner(System.in);
        StateCalculator calculator = new StateCalculator();
        int option;
        double operand;

        do{
            System.out.println("The current value is " + calculator.currentValue);
            option = StateCalculator.displayMenu();

            switch(option) {
            case 1:
                operand = getOperand("What is the second number?: ");
                calculator.add(operand);
                break;
            case 2:
                operand = getOperand("What is the second number?: ");
                calculator.subtract(operand);
                break;
            case 3:
                operand = getOperand("What is the second number?: ");
                calculator.multiply(operand);
                break;
            case 4:
                operand = getOperand("What is the second number?: ");
                calculator.divide(operand);
                break;
            case 5:
                calculator.clear();
                break;
            }

        }while(option != 6);

        keyboard.close();
    }

}

I tried running the debug feature in eclipse and discovered the problem occurs on line 29 in my getOperand method when I attempt to set operand = input.nextDouble. However, I don't understand why this would be an issue.

4
  • 1
    @TAsk Same exception, different cause Commented Jul 9, 2014 at 16:35
  • @user3580294 Accept My apologies.I didn't read question properly.Retracted Close vote.Sorry!! :) Commented Jul 9, 2014 at 16:54
  • @TAsk I still think that there's a dupe somewhere... I just don't know where. Commented Jul 9, 2014 at 16:56
  • @user3580294 May be :stackoverflow.com/questions/15443383/… Commented Jul 9, 2014 at 17:00

1 Answer 1

5

Don't call keyboard.close(); when you close keyboard (which you defined)

Scanner keyboard = new Scanner(System.in);

it closes System.in, and then your other methods can't work (because the console will not re-open). You can have multiple scanners on System.in (as long as you don't close them), or pass one (or, but please don't, use a global).

Per the javadoc,

When a Scanner is closed, it will close its input source if the source implements the Closeable interface.

Sign up to request clarification or add additional context in comments.

11 Comments

Why is it bad to use a global new Scanner(System.in)? I've done this before, which is why I'm curious. You even say that there's no need to close it. It's all going to the same place, so to me it makes sense to use one Scanner.
This answer is correct. See docs.oracle.com/javase/1.5.0/docs/api/java/util/…, where it reads "If this scanner has not yet been closed then if its underlying readable also implements the Closeable interface then the readable's close method will be invoked."
It's generally bad to use a global (especially when it could so easily be passed in). It's causing your error to close the Scanner, edited my answer to add a javadoc link.
I understand that closing the Scanner causes the issue. But that has nothing to do with using a global. It's much easier to reference a global than pass it around to a bunch of different methods. That would just muddy up the method signatures for no reason. Just use the global and never close it.
@JeffGohlke Until you want to write to another OutputStream in one caller. Then it's a nightmare. I do agree that for a simple enough program with one operation and one destination it's not an unreasonable approach. But code has a way of being used in other ways at other times.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.