简体   繁体   English

如何在Java中处理异常而不必回到try块的开头?

[英]How to handle exception in Java without having to go back to the beginning of the try block?

I've implemented exception handling in my program, but now the problem that I have is that, when an exception occurs and is handled in the catch block, instead of continuing from where it happened, it goes back to the beginning of the program, so any changes made in catch block are useless.我已经在我的程序中实现了异常处理,但现在我遇到的问题是,当异常发生并在 catch 块中处理时,它不是从发生的地方继续,而是回到程序的开头,所以在 catch 块中所做的任何更改都是无用的。

Simple example简单的例子

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);

But if I do that, the program returns to the start of the do block, and it thus resets the value of X instead of continuing from the line where the success message is.但是如果我这样做,程序将返回到 do 块的开头,因此它会重置 X 的值,而不是从成功消息所在的行继续。

I understand that this is because the repeat boolean is true at that moment and it thus triggers the while condition to start over, but if I set it to false inside of the catch block, I would potentially expose myself to an unhandled exception because someone could still try to input something invalid.我知道这是因为那时 repeat 布尔值为真,因此它触发了 while 条件重新开始,但是如果我在 catch 块内将它设置为 false,我可能会将自己暴露在未处理的异常中,因为有人可以仍然尝试输入无效的内容。

Is there a way to return control after the line where the exception was thrown once it's been handled by the catch block?一旦由 catch 块处理,有没有办法在抛出异常的行之后返回控制权?

If you remove input.nextLine(); x = input.nextInt();如果删除input.nextLine(); x = input.nextInt(); input.nextLine(); x = input.nextInt(); from the catch block without setting repeat to true, the execution will continue to the start of do and user will be asked to input value.从没有设置repeat为true 的catch块开始,执行将继续到do的开始,并且将要求用户输入值。 If the right value is entered, you can set repeat to false to break out of the do-while .如果输入了正确的值,您可以将repeat设置为 false 以跳出do-while

If your application is going to have have multiple User inputs then you should have multiple loops to handle each of those inputs since each input has the potential to possibly be wrong and generate an exception.如果您的应用程序将有多个用户输入,那么您应该有多个循环来处理每个输入,因为每个输入都有可能出错并产生异常。

In most cases, if an exception occurs because of User input then the value within the variable holding that input is not desired anyways because it's obviously wrong or at the very least has fallen to its initialized default.在大多数情况下,如果由于用户输入而发生异常,那么无论如何都不需要保存该输入的变量中的值,因为它显然是错误的,或者至少已经下降到其初始化默认值。 In this case then, normally you would want to give the User an opportunity to supply the correct input.在这种情况下,通常您希望让用户有机会提供正确的输入。 If not then don't place the prompt into a loop to begin with.如果不是,则不要将提示放入循环开始。

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!");

Although sometimes it serves a purpose I personally try to avoid working against Exceptions.尽管有时它是有目的的,但我个人会尽量避免针对异常工作。 I think it's best to avoid them if you can which is why with console applications I prefer to just use the Scanner#nextLine() method which accepts all keyboard input, for example:我认为如果可以的话,最好避免它们,这就是为什么在控制台应用程序中我更喜欢只使用接受所有键盘输入的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!");

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM