Как обработать исключение в Java без необходимости go вернуться к началу блока try? - PullRequest
0 голосов
/ 13 февраля 2020

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

Простой пример

public class Example {
   public static void main(String[] args) {
      int x;
      boolean repeat = true;
      Scanner input = new Scanner();
      do {
          try {
               x = input.nextInt();
               System.out.println("Success!");
               repeat = false;
          }
          catch(InputMismatchException e) {
              System.out.println(e.getMesasge());
              system.out.println("\nYou must enter an integer");

              //BTW am I correct in thinking the following clears the buffer?

              input.nextLine(); 
              x = input.nextInt();
          }
         } while (repeat);

Но если я это сделаю, программа вернется к началу блока do, и таким образом сбрасывает значение X вместо продолжения из строки, где находится сообщение об успехе.

Я понимаю, что это потому, что в этот момент повторное логическое значение истинно, и, таким образом, запускается условие while, чтобы начать сначала, но если Я установил его в false внутри блока catch, я потенциально мог бы подвергнуться необработанному исключению, потому что кто-то все еще может попытаться ввести что-то недопустимое.

Есть ли способ вернуть управление после строки, где было исключение бросить, как только он был обработан блоком catch?

Ответы [ 2 ]

0 голосов
/ 13 февраля 2020

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

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

Scanner input = new Scanner(System.in);
String ls = System.lineSeparator();

// We want the User to enter an inclusive number from 1 to 5.
int x = 0;
while (x < 1 || x > 5) {
    System.out.print("Enter an Integer Number from 1 to 5: --> ");
    try {
        x = input.nextInt();
        input.nextLine();   // Consume ENTER.
        System.out.println("Success! The nextInt() method accepted your input!");
        if (x < 1 || x > 5) {
            System.err.println("But...this application does not accept it!");
            System.err.println("We asked for a number from 1 to 5! Try again..." + ls);
        }
    }
    catch (InputMismatchException  ex) {
        System.out.println(ex.getMessage());
        System.err.println("Invalid Input! An Integer number from 1 to 5 only!" + ls);

        //BTW am I correct in thinking the following clears the buffer?
        /* YES you are since the nextInt() method does not consume the
           the newline character provided by the ENTER key like the nextLine()
           method does and therefore provides it on the next input request
           which in this case ultimately generates an endless loop of exceptions.
           Even if this prompt was successful and control is passed on to the 
           next prompt and if that prompt was a nextLine() method then it would 
           be basically skipped over because it would then consume that ENTER 
           key newline character provided in the last nextInt() method.  So
           with that in mind, it doesn't hurt to place input.nextline(); 
           directly after the x = input.nextInt(); ether.               */
        input.nextLine();   // Consume ENTER.
    }
}
System.out.println(x + " Was Supplied! - DONE!");

Хотя иногда это служит цели, которую я лично стараюсь избегать, работая против исключений. Я думаю, что лучше избегать их, если можете, поэтому в консольных приложениях я предпочитаю просто использовать метод Scanner # nextLine () , который принимает любой ввод с клавиатуры, например:

Scanner input = new Scanner(System.in);
String ls = System.lineSeparator();

// Prompt 1:
// We want the User to enter an inclusive number from 1 to 5.
int x = 0;
String userIN = "";
while (x < 1 || x > 5) {
    System.out.print("Enter an Integer Number from 1 to 5 (q to quit): --> ");
    userIN = input.nextLine();
    if (userIN.toLowerCase().charAt(0) == 'q') {
        System.out.println("Quitting!");
        System.exit(0);
    }
    // Is it a signed or unsigned integer number with 1 or more digits?
    if (userIN.matches("-?\\d+")) {
        System.out.println("Success! The nextLine() method accepted your input" + ls
                + "to be a string representation of an Integer value!");
        x = Integer.parseInt(userIN);
    }
    else {
        System.err.println("Invalid Input! An Integer number from 1 to 5 only!" + ls);
        continue;
    }
    if (x < 1 || x > 5) {
        System.err.println("But...this application does not accept it!");
        System.err.println("We asked for a number from 1 to 5! Try again..." + ls);
    }

}
System.out.println(x + " Was Supplied! - DONE!" + ls);

// Prompt 2:
// We want the User to enter any float or double type numerical value.
double d = Double.MIN_VALUE;
while (d == Double.MIN_VALUE) {
    System.out.print("Enter a float or double type number (q to quit): --> ");
    userIN = input.nextLine().toLowerCase().trim();
    if (userIN.charAt(0) == 'q') {
        System.out.println("Quitting!");
        System.exit(0);
    } 
    // Get rid of the type designator from value if it exists.
    if (userIN.endsWith("f") || userIN.endsWith("d")) {
        userIN = userIN.substring(0, userIN.length() - 1);
    }
    // Is it a signed or unsigned integer, float, or double type number?
    if (userIN.matches("-?\\d+(\\.\\d+)?")) {
        System.out.println("Success! The nextLine() method accepted your input" + ls
                         + "to be a string representation of an Integer, float," + ls
                         + "or double type value!");
        d = Double.parseDouble(userIN);
    }
    else {
        System.err.println("Invalid Input! A Float or Double type numerical value is required!" + ls);
        d = Double.MIN_VALUE;
    }
}
System.out.println(d + " Was Supplied! - DONE!");
0 голосов
/ 13 февраля 2020

Если вы удалите input.nextLine(); x = input.nextInt(); из блока catch, не установив repeat в значение true, выполнение продолжится до начала do, и пользователю будет предложено ввести значение. Если введено правильное значение, вы можете установить для repeat значение false, чтобы выйти из do-while.

...