Reputation: 582
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.
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.
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.
Is there a way to return control after the line where the exception was thrown once it's been handled by the catch block?
Upvotes: 0
Views: 538
Reputation: 9192
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 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!");
Upvotes: 0
Reputation: 394
If you remove 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. If the right value is entered, you can set repeat
to false to break out of the do-while
.
Upvotes: 0