Can someone please highlight to me the problem With my main method? I am getting the error exception that scanner is closed once I complete first option and try to enter another?
I think the problem I am having is from the placement of my try catch and finally blocks but not totally sure! Thanks!
/**
* Scanner used for input within program
*/
public static Scanner scanner = new Scanner(System.in);
/**
* Main method that provides user with a menu in which each number
* represents a different task in which they can carry out
*/
public static void main(String[] args) {
int menuOption=0;
do{
try {
// Declaring var for user Input (defaulted to 0)
menuOption = showMenu();
switch (menuOption) {
case 1:
add();
break;
case 2:
subtract();
break;
case 3:
generateRandomNumber();
guessRandomNumber();
break;
case 4: // invoke print loop method (use params here to get
// experience!)
break;
case 5: // invoke print sum and average
break;
case 6: System.out.println("Quitting Program...");
break;
default:
System.out.println("Sorry, please enter valid Option");
}// End of switch statement
} catch (Exception ex) {
//flush scanner
scanner.next();
}
finally {
// Finally block ensures scanner is always closed
scanner.close();
}
}while(menuOption!=6);
//Exiting message
System.out.println("Thanks for using this Program...");
The problem is that in the first iteration of the loop you are closing the scanner in the finally block. The finally block goes off every time, even if a exception isn't caught.
I'm guessing you're using exceptions for program flow (and catch-all at that!)? Don't. Exceptions are very expensive and using them for program flow clutters the code a lot.
You're using scanner.next() in your catch statement: this will ask for new input.
But since the finally block is executed right after the catch, you'll immediatly close it.
The finally block will execute regardless of exceptions or not. It is meant to clean up resources, but you're cleaning them too early.
Remove the try-catch (or make it more appropriate) and don't close your scanner in the finally block.
Close the scanner outside of the loop and get rid of the finally
do {
...
} while (...)
scanner.close();
Right now your flow of control looks like this
do {
try {
//read from scanner
}
finally {
scanner.close();
}
} while (menuOption != 6);
but this closes your scanner after first iteration.
You probably should move your do...while() inside try{...} block.
try {
do{
//read from scanner
}
while (menuOption != 6);
}
finally {
scanner.close();
}
This way your finally block which ensures closing of scanner will be outside of loop.
Mayby you get and exception and the code enters in the catch then in finally
Tray to see if you enter in the catch block
Related
I am very new to java and I am trying out error handling. I am pretty proficent in python and I know the error handling in python would go
while True:
try:
*some code*
except IndexError:
continue
break
I would like to know what the equivalent of a retry loop after exception is in java
EDIT:
This is what I have so far, however whenever a exception is thrown it does an infinite loop saying "Enter an Short: Error Try again."
while(true)
{
try {
System.out.print("Enter an Short: "); //SHORT
short myShort = reader.nextShort();
System.out.println(myShort);
break;
}
catch (InputMismatchException e) {
System.out.println("Error Try again.");
continue;
}
}
To clarify what exactly I would like is. When "InputMismatchException" is thrown the loop re runs and prompts the user again and it does this until the user gives the correct input. I hope that clarifies what I would like it to do.
What you have is almost good as #Thomas mentioned. Just need to add some brackets and semicolons. It should look line following code.
while(true){
try{
// some code
break; // Prevent infinite loop, success should break from the loop
} catch(Exception e) { // This would catch all exception, you can narrow it down ArrayIndexOutOfBoundsException
continue;
}
}
As your question asks about error handling and you showed IndexError as an example, the equivalent in Java could be:
try {
//*some code*
}
catch(ArrayIndexOutOfBoundsException exception) {
//handleYourExceptionHere(exception);
}
About ArrayIndexOutOfBoundsException, you take a look here, in the documentation. About Exceptions, in general, you can read here.
EDIT, according to your question edition, adding more information...
while(true)
{
try {
System.out.print("Enter a short: ");
short myShort = reader.nextShort();
System.out.println(myShort);
}
catch (InputMismatchException e) {
System.out.println("Error! Try again.");
//Handle the exception here...
break;
}
}
In this case, when the InputMismatchException occurs, the error message is exhibited and the break should leave the loop. I do not know yet if I understand well what you are asking, but I hope this helps.
To the help of #Slaw he determined that scanner would keep inputting the same value unless I closed it at the end of the loop and here is the working code.
while (true)
{
Scanner reader = new Scanner(System.in);
try
{
System.out.print("Enter an Short: "); //SHORT
short myShort = reader.nextShort();
System.out.println(myShort);
reader.close();
break;
}
catch (InputMismatchException e)
{
System.out.println("Error Try again.");
}
}
I have a homework assignment to create a class with a looping menu to manage a queue of cars. We learned queues in our last class.
My menu works perfectly fine until it catches InputMismatchException or QueueEmptyException, after which it goes into endless loop, not even stopping at the userInput.nextInt();. It works when it catches QueueFullException, but not the others.
My code is:
import java.util.*;
public class CarQueueManagement {
public static void main(String[] args) throws InputMismatchException, QueueFullException{
ArrayQueue queue = new ArrayQueue(3);;
Scanner userInput = new Scanner(System.in);
int carNum;
int choice = 0;
queue.add(1);
OUTER:
while (true) {
try{
System.out.println("ΜΕΝΟΥ:\n\t1. Άφιξη αυτοκινήτου");
System.out.println("\t2. Αναχώρηση αυτοκινήτου\n\t3. Κατάσταση ουράς\n\t4. Έξοδος");
System.out.print("\n\tΕπιλογή (1-4): ");
choice = userInput.nextInt();
switch (choice){
case 1:
System.out.print("\n\tΆφιξη αυτοκινήτου:\n\t\tΑριθμός Αμαξιού");
carNum = userInput.nextInt();
queue.add(carNum);
break;
case 2:
if(queue.isEmpty()){
System.out.println("\n\tΗ ουρά είναι άδεια, δεν χριάζεται διαγραφή.\n\n");
break;
}
String answer;
while(true){
System.out.print("\n\tΑναχώρηση αυτοκινήτου\n\t\tΕπιβεβαίωση; (y/n): ");
answer = userInput.next();
if(answer.equals("y")){
queue.remove();
break;
}
else if(answer.equals("n"))
break;
}
break;
case 3:
System.out.println("\n\tΚατάσταση ουράς:");
if(queue.isEmpty()) System.out.println("\t\tΗ ουρά είναι άδεια.\n\n");
else if(queue.isFull()) System.out.println("\t\tΗ ουρά είναι γεμάτη.\n\n");
else System.out.println("\t\tΗ ουρά έχει άδιες θέσοις.\n\n");
break;
case 4:
System.out.print("\n\nΕξοδος");
break OUTER;
default:
break;
}
}catch (InputMismatchException exc){
System.out.println("\t\tΛΑΘΟΣ ΕΙΣΑΓΩΓΗ\n");
}catch(QueueEmptyException exc){
System.out.println("\t\t" + exc.getMessage() + "\n");
}catch(QueueFullException exc){
System.out.println("\t\t" + exc.getMessage() + "\n");
}
}
}
}
From the intro section of java.util.Scanner docs (emphasis mine):
When a scanner throws an InputMismatchException, the scanner will not pass the token that caused the exception, so that it may be retrieved or skipped via some other method.
Without the details, your while(true) loop is:
while (true) {
try{
choice = userInput.nextInt();
switch (choice){
case 1:
...
}
} catch (InputMismatchException exc){
// Do nothing.
}
}
When the user enters something that can't be converted to an integer, the Scanner throws an InputMismatchException, which you catch and ignore. Then the while loop goes back to the top, where it tries to execute userInput.nextInt()... but the Scanner is still looking at the same invalid input, so it immediately throws another InputMismatchException, which you catch and ignore again. Execution continues at the top of the while loop, where it calls nextInt() again... and the cycle continues forever.
You have to force the Scanner to skip the bad input, so your catch block should look something like this:
}catch (InputMismatchException exc){
System.out.println("\t\t[chastise the user in Greek]\n");
userInput.next(); // Skip invalid input.
}
Other Advice
As a general rule, lots of small methods are easier to understand than one large method. The nested while loops and switch statement were especially hard to follow. I was only able to find the bug by breaking that gigantic main method into many smaller, private static methods.
At the very least, each menu item could be handled in its own method. I also got rid of the break label by putting the whole menu into a separate method, which returned a boolean indicating whether the user was done or not. That reduced the whole loop inside main to:
boolean done = false;
while (! done) {
try{
done = handleUserInput(queue, userInput);
} catch (InputMismatchException exc) {
System.out.println("\nINPUT ERROR\n");
userInput.next();
} // Other catch blocks as before...
}
My handleUserInput doesn't do much --- it gets user input, determines which method should handle that input, and then returns true or false... It could be made simpler than this, too.
private static boolean handleUserInput(
final ArrayQueue queue,
final Scanner userInput
) {
boolean done = false;
printMenu();
int choice = userInput.nextInt();
switch (choice) {
case 1:
addToQueue(queue, userInput);
break;
case 2:
removeFromQueue(queue, userInput);
break;
case 3:
displayQueue(queue);
break;
case 4:
printExitMessage();
done = true;
break;
default:
break;
}
return done;
}
Splitting the various menu activities into separate methods made them much easier to follow. For example, when the logic was all mixed together in main, it was hard to tell if variables like carNum or answer were part of the problem. In this version, carNum is a local variable trapped inside the addToQueue method, so when I'm working anywhere else, I can completely ignore it.
I want to make a try-catch exception that only accept 1-5 or 9 input. So I wrote the following code.
try {
step1 = scanner.nextInt();
} catch (Exception ex) {
System.out.println("Error! Input accept integers only. Input 1-5 or 9");
System.out.println("");
continue;
}
The result is that if I input an invalid number, it gave me an error (That's true). But when I input a character, it gave me an infinite loop. How can I solve the problem?
Since i don´t know how your loop looks i´ll just go with an endless loop in my answer. In the normal case, the nextInt method wont catch the carriage return, and if you input something that is not a number you need to call nextLine to catch this. If you don´t do this you might run into an infinity loop if you are using any kind of loop that just asks for nextInt. This could solve the problem:
while(true) {
int step1;
try {
step1 = s.nextInt();
} catch (InputMismatchException e) {
System.out.println("Error! Input accept integers only. Input 1-5 or 9");
System.out.println("");
} finally { // Use a finally block to catch the carriage return, no matter if the int that got input was valid or not.
s.nextLine();
}
}
Maybe you must parse input before decision making.
Sorry for my bad English, I'm not a native speaker also.
try this, which make all the tests
int step1;
while (true)
{
Scanner scanner = new Scanner(System.in);
try {
step1 = scanner.nextInt();
if (((step1>=1) && (step1<=5)) || (step1==9))
// BINGO
break;
}
catch (Exception ex)
{
}
System.out.println("Error! Input accept integers only. Input 1-5 or 9");
System.out.println("");
// it loops ther
}
System.out.println("You are done ! "+step1);
I am making a basic application where it trains your math skills. I have this code:
while (true)
{
try
{
int userAnswer;
System.out.println("Type quit to exit to the menu!");
int randInt = r.nextInt(num2);
System.out.println(num1 + " + " + randInt + " =");
userAnswer = in.nextInt();
if(userAnswer == num1 + randInt) System.out.println("Correct!");
else System.out.println("Wrong!");
break;
}
catch(Exception e)
{
}
}
When someone prints out a d or something in the answer, the try catch goes. But, then it goes to the while loop and repeatedly spams Type quit to exit to the menu and then something like 1 + 2 = infinitely... I think I know what's wrong, userAnswer has been assigned already as something that throws an exception that goes to the catch and it just keeps printing those and goes to the catch and goes back because userAnswer is already assigned. I think this is what is happening, I could be wrong. Please help!
EDIT: I forgot to make this clear, but I want the question to be re-printed again, exiting out of the loop goes to a menu where you can't get the question back, I want it to redo what's in the try catch...
You should never catch an Exception without handling it.
catch(Exception e)
{
System.out.println("An error has occured");
break;
}
This should stop your program from looping infinitely if an Exception occurs.
If user input comes as letter it will get an exception because you are trying to read(parse) as integer. So your catch clause is in the loop you have to write break in there to go out from loop.
Still i will suggest you to getline as string and than compare with your cli commands (quit in your case) than you can try to parse it as an integer and handle loop logic.
You're not breaking the while loop if there is a mismatch
while(true)
{
try
{
}
catch(InputMisMatchException e)//I suggest you to use the exact exception to avoid others being ignored
{
System.out.println("Thank you!");
break;//breaks the while loop
}
}
Yoy're not breaking the loop in case of Exception occurs.
Add break; statement in the catch block to run your program without going to infinite loop, in case exception occurs.
Since the given answers don't match your requirement I'll solve that "riddle" for you.
I guess what you didn't knew is that the scanner won't read the next token if it doesn't match the expectation. So, if you call in.nextInt() and the next token is not a number, then the scanner will throw an InputMismatchException and keeps the reader position where it is. So if you try it again (due to the loop), then it will throw this exception again. To avoid this you have to consume the erroneous token:
catch (Exception e) {
// exception handling
in.next();
}
This will consume the bad token, so in.nextInt() can accept a new token. Also there is no need to add break here.
Mind that in.next() reads only one token, which is delimited by a whitespace. So if the user enters a b c, then your code will throw three exception and therefore generate three different question befor the user can enter a number. You can avoid that by using in.nextLine() instead. But this can lead into another problem: Scanner issue when using nextLine after nextXXX, so pay attention to that :).
I have some code that involves checking user input to see if it the input entered is a string or an int, and will execute different code depending on the result. I am using Integer.parseInt in order to determine if the user input is an integer or not, with the NumberFormatException being thrown if it is not.
However, in order to control the flow of the code, i am using a try/catch statement, with the catch block being used to contain code that will be run if the user's input is a string (i.e NumberFormatException) is thrown.
Qn
Is this an acceptable way of using the try/catch block? I've try googling this but all i could find were examples of the catch block being used to handle the Exception thrown instead of it being used as i am doing.
import java.io.*;
import java.util.*;
public class Datafile{
private static Scanner input = new Scanner(System.in);
public static void main(String[] args) throws IOException {
BufferedWriter bw = new BufferedWriter(new FileWriter("C:\\Users\\Kence\\workspace\\Java 8 - Beyond the Basics - Working Files\\Practice Programs\\src\\Practice Data Edited",true));
String data = null;
boolean end = false;
boolean cont = true;
String dataEntered = null;
int menuChoice = printMenu();
while(!end){
switch(menuChoice){
case 1:
System.out.println("Please enter a line of data or press 0 to exit back to the main menu");
dataEntered = input.nextLine();
try {
if(Integer.parseInt(dataEntered) == 0){
break;
}
} catch (Exception e) {
data += dataEntered + "\n";
while(cont){
System.out.println("Data entered.Please enter the next line of data or press quit to exit back to the main menu.");
dataEntered = input.nextLine();
if(Integer.parseInt(dataEntered) == 0){
cont = false;
break;
}else{
data+= dataEntered;
System.out.println("Current data entered is " + dataEntered);
}
}
}
break;
case 2:
System.out.println("2 Entered");
break;
case 3:
System.out.println("3 Entered");
break;
case 4:
System.out.println("4 Entered");
break;
}//End of switch statement
menuChoice = printMenu();
}
input.close();
}//End of main
public static void printStars(){
for(int i = 0; i<66 ; i++){
System.out.print("*");
}
System.out.println();
}
public static int printMenu(){
printStars();
System.out.println("System Started");
printStars();
System.out.println("Enter 1 to input a new line of data");
System.out.println("Enter 2 to list all data");
System.out.println("Enter 3 to save existing data");
System.out.println("Enter 4 to load data");
printStars();
return Integer.parseInt(input.nextLine());
}
}
It isn't considered best practices to use a try/catch block for control flow, but it is "acceptable" if you don't care about best practices.
See Determine if a String is an Integer in Java for examples of other ways to check if a number is an integer. You could use one of those examples and then if it is an integer check if it's equal to zero.
Also, in your code it appears your second call to Integer.parseInt(dataEntered) could still throw an exception that would not be caught.
Exceptions should generally only be used in exceptional cases (see where the name comes from?). They are especially bad in tight loops because the execution overhead is high. Having invalid user input seems like a rather common occurrence, so I would look for another way. Take a look at this answer.
But this all depends on the language. In Python for example, try/catch is the de-facto way of coding (duck-typing).