Try-Catch statements in Java

26,147

Solution 1

When you use a try-catch block, you're essentially telling the compiler that you're going to take care of displaying the error messages--no built-in messages will show. Instead, whatever error prompts you include in the catch statements will show.

When I run your program, I see your error messages, but no built-in Java error messages; this is how it should be. Really, the errors are being thrown--but you're catching them, so Java doesn't display the default message on the console.

Regarding your comment at the end of the program:

Look at what's happening if the user enters an incorrect data type at the menu prompt; menuItem is still zero. Thus, all the if statements evaluate to false. Thus, the else statement runs, which terminates the program.

Solution 2

The other answers explain why you don't get the output you are expecting. I'd also like to important couple of programming mistakes that you are making:

1) Don't catch Exception like that!

When you catch Exception you catch each and every possible subtype of Exception that could be thrown by the code. In your case, you are clearly expecting an InputMismatchException to be throw, but the nextXxx methods can also throw other exceptions such as NoSuchElementException or IllegalStateException. And then there is the possibility of others such as NullPointerException which would be indicative of a bug.

You should explicitly catch and handle the exceptions that you are expecting, and leave the others for more generic unexpected exception handling.

2) Do print out the Exception error message

It will give you details of the actual error; e.g.

  try {
    menuItem = reader.nextInt(); 
  }
  catch(InputMismatchException e){
    reader.nextLine(); // Clear the input stream to avoid an infinite loop
    System.out.println(e.getMessage());
    System.out.println("Please a valid number 1-5.");
  }

In fact, it an exception is unexpected, it is a GOOD IDEA to print out or log the exception's stack trace so that you (or the person who has to deal with error reports from users) can figure out what actually happened.

3) When a setter's validation fails, throw an exception:

Your setters do this kind of thing:

public boolean setInterestRate(double ir){
    if(ir >= 0 && ir <= 1){
        interestRate = ir;
        return true;
    }
    else return false;
}

The problem is threefold:

  • Setters don't normally return anything. It is not the normal idiom.
  • If the caller of the method doesn't check your setter has returned false, it won't notice that the set operation didn't happen.
  • Nothing tells anything why the set operation failed.

Write it like this:

public boolean setInterestRate(double ir){
    if(ir >= 0 && ir <= 1){
        interestRate = ir;
    }
    else {
        throw new IllegalArgumentException(
            "Interest rate not between 0 and 1 (" + ir + ")");
    }
}

Solution 3

If an invalid menu item is entered you get menuItem = 0 which falls to the bottom of your if ladder and hits the final break.

Solution 4

Just have a continue after the last statement of your catch block as follows;

catch(Exception e){
reader.nextLine(); // Clear the input stream to avoid an infinite loop
System.out.println("Please a valid number 1-5.");
continue;
}

Because you allow the program to continue after catching the exception which halts your program as is progress along.

Hope this helps.

Share:
26,147
realityChemist
Author by

realityChemist

Materials science and engineering PhD candidate, enthusiast in many things

Updated on December 01, 2020

Comments

  • realityChemist
    realityChemist over 3 years

    UPDATE: Thanks for the advice about keeping codes SSCCE. Like I said, this is my first time posting here. I'll definitely take the time next time to make sure the code is sufficiently trimmed down before I post here next time.


    So I'm writing a program for my computer science class, and having a strange problem that I can't figure out. I tried to make my program robust by using try/catch statements to stop invalid data type input before it could foul up and end the entire program, but it doesn't seem to be working. When an invalid data type is entered, the program ends without displaying any of Java's standard error messages in the window. I have no idea why this is, but I assume I'm using the try/catch statements incorrectly. Here are the two classes for my program:

    /* The core class for the finance calculations to be done in the FinanceApp class. */
    
    public class FinanceCore{
      // Instance variables
      int numYears;
      double principal;
      double interestRate;
      double balance;
    
      public FinanceCore(){
        numYears = 0;
        principal = 0;
        interestRate = 0;
        balance = 0;
      }
    
      // Mutator methods that return boolean values depending on whether the input was valid or not
      public boolean setYears(int y){
        if(y >= 0){
          numYears = y;
          return true;
        }
        else return false;
      }
    
      public boolean setPrincipal(double p){
        if(p >= 0){
          principal = p;
          balance = principal;
          return true;
        }
        else return false;
      }
    
      public boolean setInterestRate(double ir){
        if(ir >= 0 && ir <= 1){
          interestRate = ir;
          return true;
        }
        else return false;
      }
    
      // Two accessors
      public int getYears(){
        return numYears;
      }
    
      public double getPrincipal(){
        return principal;
      }
    
      // This method calculates and returns the balance at the end of each year
      public double plusYear(){
        balance = balance*(1+interestRate);
        return balance;
      }
    }
    

    /* This program recieves three pieces of data (interest rate, principal amount, number of years) and generates an output
    * table that shows how much money will be in a fund with the given parameters at the end of every year. */
    
    import java.util.Scanner;
    
    public class FinanceApp{
    
      public static void main(String[]args){
        // First, we will declare our global variables, and set them to default values
        Scanner reader = new Scanner(System.in);
        FinanceCore account = new FinanceCore();
        int menuItem = 0;
    
        // Now, we'll greet the user (because we're friendly like that)
        System.out.println("Welcome! Please select a menu option below.");
    
        while(true){
          /* Now, our first user interface: a menu system that displays four options to the user arranged in
           * columns for aesthetic effect. This is accomplished using the printf method.
           */
    
          System.out.printf("%n%-20s%-20s%n%-20s%-20s%n%-20s%n",
            "Set Principal[1]","Set Interest Rate[2]","Set Timespan[3]","Calculate[4]","Quit[5]");
    
          System.out.print(": ");
    
          // Now we get the user input until it is valid, and catch and errors in input type
          try {
            menuItem = reader.nextInt(); 
          }
          catch(Exception e){
            reader.nextLine(); // Clear the input stream to avoid an infinite loop
            System.out.println("Please a valid number 1-5.");
          }
    
          // The code for setting the principal amount
          if(menuItem == 1){
          while(true){
            System.out.print("Please enter the principal investment amount: ");
    
            try{
              if(account.setPrincipal(reader.nextDouble()));
              break;
            }
            catch(Exception e){
              reader.nextLine(); // Clear the input stream to avoid an infinite loop
              System.out.println("Please enter a valid dollar amount.");
            }
          }
        }
        // The code for setting the interest rate
        else if(menuItem == 2){
          while(true){
            System.out.print("Please enter the quarterly interest rate: ");
            try{
              if(account.setInterestRate(reader.nextDouble()));
              break;
             }
             catch(Exception e){
               reader.nextLine(); // Clear the input stream to avoid an infinite loop
               System.out.println("Please enter a valid decimal number between 0 and 1 (inclusive).");
             }
           }
         }
    
         // The code for setting the number of years
         else if(menuItem == 3){
           while(true){
             System.out.print("Please enter the number of years the account will exist: ");
             try{
               if(account.setYears(reader.nextInt()));
               break;
             }
             catch(Exception e){
               reader.nextLine(); // Clear the input stream to avoid an infinite loop
               System.out.println("Please enter a valid integer value.");
             }
           }
         }
    
         // This part actually executes the calculation
         else if(menuItem == 4){
           System.out.printf("%-10s%-10s%n%-10d%-10.2f%n","YEAR","BALANCE",0,account.getPrincipal());
           int count = 1;
           for(int c = account.getYears(); c > 0; c--){
             System.out.printf("%-10d%-10.2f%n",count,account.plusYear());
             count++;
           }
         }
    
         // If the user enters any other number, the program quits
         else
           break;
         }
       }
     }
    

    Note that there is one persistent problem with this program that I can't seem to fix. For some reason, every time the user enters an invalid data type at the menu selection prompt, the program ends (although without any errors being thrown).