Попробуйте/поймать в Java

Может ли кто-нибудь дать мне подсказку, почему эта попытка и улов не работают? Он выдает исключение сканера вместо того, чтобы печатать ожидаемое сообщение.

import java.util.*;
import java.io.*;
import java.math.*;
import javax.swing.*;

public class Main {
    public static void main(String[] args) {
        Boolean test = true;
        while (test == true) {
            try {
                double x, y;
                String operator;
                Scanner scan = new Scanner(System.in);
                Scanner scan_2 = new Scanner(System.in);
                Scanner ScanOperator = new Scanner(System.in);
                System.out.println(" Enter a double value: ");
                x = scan.nextDouble();
                System.out.println(" Enter another double value: ");
                y = scan_2.nextDouble();
                System.out.println(" Enter a operator for the operation you want to execute, or X if you want to quit: ");
                operator = ScanOperator.nextLine();
                if (operator.equals("x") || operator.equals("X")) {
                    test = false;
                    System.out.println("No calculation was made!!!");
                }
                System.out.println(Calculation(operator, x, y));
            } catch (NumberFormatException nfe) {
               JOptionPane.showMessageDialog(null,"Input must be a number.");
            }
        }
    }

    public static double Calculation(String operator, double x, double y) {
        double result = 0;
        double myAdd = 0;
        double mySub = 0;
        double myMult = 0;
        double myDiv = 0;
        double myPower = 0;
        double myMod = 0;

        if (operator.equals("+")) {
            myAdd = x + y;
            result = myAdd;
        } else if (operator.equals("-")) {
            mySub = x - y;
            result = mySub;
        } else if (operator.equals("*")) {
            myMult = x * y;
            result = myMult;
        } else if (operator.equals("/")) {
            myDiv = x / y;
            result = myDiv;
        } else if (operator.equals("^")) {
            myPower = Math.pow(x, y);
            result = myPower;
        } else if (operator.equals("%")) {
            myMod = x % y;
            result = myMod;
        } else {
        }

        return result;
    }
}

person Tony    schedule 14.01.2010    source источник
comment
Что вам говорит исключение?   -  person nos    schedule 15.01.2010
comment
Этот код в порядке. Я могу запустить его как локально.   -  person Thunderhashy    schedule 15.01.2010


Ответы (7)


Все просто: программа выдает ScannerException, но ваш try catch может перехватывать только NumberFormatException, вам нужно добавить еще одно предложение catch, чтобы перехватывать ScannerException, или перехватывать только общее исключение.

например, когда вы говорите:

 } catch (NumberFormatException nfe) {     
     JOptionPane.showMessageDialog(null,"Input must be a number.");
 }

это только указывает, как поймать NumberFormatException.
Чтобы перехватить все исключения, вам нужно сделать это:

 } catch (NumberFormatException nfe) {     
     JOptionPane.showMessageDialog(null,"Input must be a number.");
 }catch (Exception e){
     JOptionPane.showMessageDialog(null,"Generic exception caught");
 }

В этом случае второй перехват получит все, что не было перехвачено в первом перехвате, потому что все исключения расширяют класс Exception, вы можете перехватывать все производные классы с помощью этого оператора.

Однако, поскольку перехват Exception сам по себе не одобряется, вы также можете сделать:

 } catch (NumberFormatException, ScannerException e) {     
     JOptionPane.showMessageDialog(null,"Input must be a number.");
 }

Чтобы поймать оба исключения в одном блоке.

person zmbush    schedule 14.01.2010
comment
Хотя я бы рекомендовал перехватывать конкретное исключение, которое вы хотите перехватить — в данном случае исключение сканера — вместо общего перехвата исключения. Но это правильно. - person aperkins; 15.01.2010
comment
Мой личный фаворит — это catch (Throwable t). - person Andres; 15.01.2010
comment
Обратите внимание, что ScannerException не существует в JDK, и что NumberFormatException также не генерируется в этом блоке. - person akf; 15.01.2010
comment
Если вы нашли вопрос полезным, рекомендуется принять ответ (т.е. поставить галочку на ответе, который вам понравился больше всего) - person zmbush; 15.01.2010

Вы пытаетесь поймать исключение NumberFormatException. Вам нужно добавить оператор catch для ScannerException, так как он отличается от NumberFormatException.

person Jeff    schedule 14.01.2010
comment
В Java нет ScannerException - person Thunderhashy; 15.01.2010

Вам нужно поймать ScannerException или что-то в этом роде.

В этом коде вы перехватываете только NumberFormatException .

Попробуйте что-нибудь вроде этого:

    try {
       ...
    } catch (NumberFormatException, ScannerException exception) {
       JOptionPane.showMessageDialog(null,"Input must be a number.");
    }
person Pedro Ghilardi    schedule 14.01.2010
comment
Простите меня, если я ошибаюсь, но разве так не должно быть: catch (NumberFormatException, ScannerException e) { - person zmbush; 15.01.2010
comment
как мы можем поймать 2 исключения в одном и том же блоке catch? - person Thunderhashy; 15.01.2010

Вы ловите неправильное исключение.

person Anon.    schedule 14.01.2010

Ваш код не будет выдавать ошибку NumberFormatException. Вместо этого вы должны поймать InputMismatchException.

Глядя на nextDouble в Scanner, кажется, что код Scanner обрабатывает NumberFormatException за вас, а затем выдает исключение другого типа:

от java.util.Scanner:

public double nextDouble() {
    // Check cached result
    if ((typeCache != null) && (typeCache instanceof Double)) {
        double val = ((Double)typeCache).doubleValue();
        useTypeCache();
        return val;
    }
    setRadix(10);
    clearCaches();
    // Search for next float
    try {
        return Double.parseDouble(processFloatToken(next(floatPattern())));
    } catch (NumberFormatException nfe) {
        position = matcher.start(); // don't skip bad token
        throw new InputMismatchException(nfe.getMessage());
    }
} 

Когда вы столкнетесь с такой проблемой, я рекомендую вам сначала просмотреть исходный код Java. Это отличный ресурс.

Также обратите внимание, что в JDK нет ScannerException.

person akf    schedule 14.01.2010

Просто ловите InputMismatchException вместо NumberFormatException и все работает нормально.

person Thunderhashy    schedule 14.01.2010
comment
хорошо работает, когда вы вводите буквы вместо цифр в подсказках ввода? - person akf; 15.01.2010

Почему бы просто не сделать:

String input = scan.nextLine();
if(!input.matches("\\d+")) { // regex for 1 or more digits
    System.err.println("Input must be at least 1 digit!");
    continue; // goes back to the top of the loop
}
double dbl = Double.valueOf(input);

К вашему сведению, фактическое регулярное выражение для двойной точности будет [цифра][.][цифра] с необязательным [.][цифра].

person Droo    schedule 15.01.2010