Как узнать, какая переменная генерирует исключение?

#java

#java

Вопрос:

Я пишу программу, которая вычисляет чаевые и общую сумму из счета и ставки чаевых.

 public void takeUserInput() {
    Scanner sc = new Scanner(System.in);    
    double billAmount;
    int tipRate;

    try {
        System.out.print("What is the bill? ");
        billAmount = sc.nextDouble();
        System.out.print("What is the tip percentage? ");
        tipRate = sc.nextInt();

        tc.calculate(billAmount, tipRate);
    } catch (InputMismatchException e1) {
        String errorMessage = "Please enter a valid number for the ";
        // errorMessage  = billAmount or
        // errorMessage  = tipRate ?
    }
  

Я ищу способ узнать, какая переменная вызывает исключение InputMismatchException, чтобы я мог добавить имя переменной в переменную ErrorMessage и распечатать на экране.

Комментарии:

1. @Andreas Я знаю этот метод, но мне нужно имя переменной.

2. Ни один из них не выдал бы это исключение, если бы вы просто проверили правильность перед вызовом nextXxx() , используя hasNextXxx() .

3. @Andreas Я не использую операторы цикла.

4. Где в этом предыдущем комментарии я говорил что-нибудь о циклах?

5. @Andreas Извините, я знал, что этот метод используется только в цикле.

Ответ №1:

Есть несколько простых способов добраться туда:

  1. Вызовите hasNextXXX() перед вызовом nextXxx() .
  2. Если вы используете один блок try / catch для каждого ввода, в вашем блоке catch очень ясно, какая переменная вызвала проблему (затем вы можете вызвать общий метод с конкретным сообщением об ошибке, чтобы избежать дублирования кода)
  3. Вы могли бы использовать ссылочные типы для своих переменных; если вы используете Double / Integer вместо double / int … вы можете проверить, какая из двух переменных по-прежнему равна нулю
  4. Вы вводите небольшую логическую переменную, например billAmountIsValid . Изначально эта переменная имеет значение false, вы превращаете ее в true после вызова nextDouble() . Затем вы можете легко проверить в своем блоке try, получили ли вы действительный счет.

После еще некоторых размышлений: вы действительно хотите комбинацию 1 2: вы видите; когда пользователи вводят правильное количество счетов; почему вы хотите забыть об этом значении, когда второе значение дает неверное второе значение? Нет — вы должны выполнять цикл для каждой переменной, пока не получите действительный ввод. И только тогда вы начинаете запрашивать следующее значение!

Комментарии:

1. 4. Вызовите hasNextXxx() before nextXxx() .

2. Спасибо. Хорошая идея; добавил это в список в качестве первой записи!

3. См. Следующее, почему отказ от использования исключений (вариант 1) может быть лучшим решением: считаются ли исключения как поток управления серьезным антипаттером? Если да, то почему?

4. @Andreas Спасибо, я не знал, что этот способ будет антипаттерновым.

5. @GhostCat я решил с помощью ответа Уэстона. Извините. На данный момент его путь для меня прост.

Ответ №2:

Переменная не генерирует исключение, выполняется оценка правой части присваивания переменной, и поэтому в исключении нет информации, указывающей, какой переменной она собиралась присвоить это, если бы это удалось.

Вместо этого вы могли бы рассмотреть новый метод, который включает в себя сообщения с запросами и повторные попытки:

 billAmount = doubleFromUser(sc, "What is the bill? ", "bill");
  

Где doubleFromUser :

 static double doubleFromUser(Scanner sc, String prompt, String description){
    while(true) { //until there is a successful input
        try {
            System.out.print(prompt); //move to before the loop if you do not want this repeated
            return sc.nextDouble();
        } catch (InputMismatchException e1) {
            System.out.println("Please enter a valid number for the "   description);
        }
    }
}
  

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