Exception Handling (try...catch...finally) with User Defined Exception

- Exception is an Object in Java
- Throwable is Superclass of all exceptions
- Exceptions could be Checked or Un-Checked type
- Checked exceptions needs to fix at compile time, such as IOException, InterruptedException
(Compiler checks for everything except run-time exceptions which are called un-checked)
- Un-checked exceptions occurs at run-time, such as NullPointerException
(These exceptions needs to identified at development and UAT (User Acceptance Test) phase )
- Use try...catch...finally block to deal with exceptions of both types (checked and un-checked)
- There could be multiple "catch"blocks for one try block
- Multiple "catch" blocks are arranged in the order of specific to generic
For example, upper catch block should contain code specific error, such as IOException might be followed by generic exception such as Exception. (The Exception class us use to handle generic exception because it is Super-class of Checked and Un-checked exceptions, os it covers those error types)
- Error is beyond the application scope and mainly related to system, so it is advice not to catch error and let it handle by the system to fix the root cause, such as OutOfMemoryError. Error might lead to application might crash.  
- Error is an irrecoverable condition occurs at runtime.

try {

} catch (IOException ) {

} catch (Exception) {

}
- In case of java application main() function can not use with "throws", we have to handle all checked exceptions at main() level unlike other methods which could keep throwing exceptions to the caller using "throws"

-Exception Hierarchy: 

=======================================================
Example: To demonstrate different patterns of Exception usage
import java.util.HashMap;
import java.util.Map;
/**
 * Class defining user defined exception for authentication
 */
public class AuthenticationException extends Exception {  
     static Map errorMap = new HashMap();
     //static map of error code and description, 
     //can be created after reading properties file
     static {
          //Map of Error code to Error Description
          //Transfer below mapping to Properties file for Internationalization
          //of error message based on the User Locale
          errorMap.put("E7", "Authentication Failure");
          errorMap.put("E8", "User is locked after 3 wrong login attempts.");
     }    
     /**
      * Constructor to display specific message based on error code
      * @param errorCode to print related error description
      */
     public AuthenticationException(String errorCode) {
          System.out.println(errorCode + ":" + errorMap.get(errorCode));
     }    
     /**
      * Default constructor to display default message 
      * when no error code is specified
      */
     public AuthenticationException() {
          System.out.println("Default Error message");
     }
}
-------------------------------------------------

/**
 * Class to test exception handling
 *
 */
public class TestExceptions {
     public static void main(String[] args) {
          //1. calling method which throws InterruptedException 
          //which needs to be handled by caller using try ..catch
          try {
               foo1();
          } catch (InterruptedException e) {
               e.printStackTrace();
          }
          //2. no need to catch any exception, as foo2() is not 
          //throwing any exception unlike foo1()
          foo2();
          //3. calling method which throws User defined 
          //exception AuthenticationException
          try {
               foo3(false);
          } catch (AuthenticationException e) {
               e.printStackTrace();
          }
     }
     /**
      * Method to demonstrate throws in exception handling
      * @throws InterruptedException
      */
     public static void foo1() throws InterruptedException {
          Thread.sleep(1);
     }
     /**
      * Method to demonstrate, how to handle error at 
      * method level instead throwing them to caller
      */
     public static void foo2() {
          try {
               Thread.sleep(1);
          } catch (InterruptedException e) {
               e.printStackTrace();
          }
     }
     /**
      * Method to demonstrate how to use User defined exceptions
      * @param success
      * @throws AuthenticationException
      */
     public static void foo3(boolean success) throws AuthenticationException {
          if (!success) {
               throw new AuthenticationException("E7");
          }
     }
}