Exception Handling - Customized Exception Handling using Try/Catch

Exception Handling - Customized Exception Handling using Try/Catch
In case of an runtime exception, exception arises in the application if we didn't handle the code, 
Handling the unhandled exception which is raised by the application is done by the JVM through its default exception handler. The problem with the default exception handling is, it abnormally terminates the application. which is not a good practice.

For example, lets take simple java class which causes abnormal termination.
package com.learning.exceptionhandling;

public class SampleClass {

 public static void main(String[] args) {
  System.out.println("I am Bharani Ravi Kanth R");
  System.out.println("My age is  " + 54 / 0);
  System.out.println("I am a DevOp");
 }
}

lets run this code.

Output:

I am Bharani Ravi Kanth R
Exception in thread "main" java.lang.ArithmeticException: / by zero
 at com.learning.exceptionhandling.SampleClass.main(SampleClass.java:8)

You can see the application terminated abnormally.
System.out.println("My age is  " + 54 / 0);
the above line of code caused the issue and terminated immediately and the remaining code is never  executed.

So, that's why we need to handle the code for graceful termination of the code,

Before handling the code first we need to know what is Risky Code.
The line of code which causes exception is called risky code.  In the above example the line
System.out.println("My age is  " + 54 / 0);
is said to be risky code.

lets try with the above example handle the code using try catch, risky code should be inside try block and if an exception is caused, the handled code should be inside catch block. which is as below.
package com.learning.exceptionhandling;

public class SampleClass {

 public static void main(String[] args) {

  System.out.println("I am Bharani Ravi Kanth R");
  try {
   System.out.println("My age is  " + 54 / 0);
  } catch (ArithmeticException e) {
   System.out.println("My age is  " + 54 / 2);
  }
  System.out.println("I am a DevOp");
 }
}

In the above class :

Risky code,
System.out.println("My age is  " + 54 / 0);

Catch block:  Type of Exception which can be caused by Risky Code  is ArthmeticException, catching the exception of type ArthmeticException, Which is nothing but the catch block is activated only if there is an arthmetic exception.

Handled code:
System.out.println("My age is  " + 54 / 2);

Lets run the class.

Output:
I am Bharani Ravi Kanth R
My age is  27
I am a DevOp

You can see the now handled code is executed, and rest of the statements of the class are also executed without any abnormal termination.


Control Flow of try/catch Block:

when an exception is handled, in what order the statements in the application are executed can be seen in this control flow.

Lets see all the cases programmatically.

Case 1: If there is no exception raised by the risky code.
package com.learning.exceptionhandling;

public class SampleClass {

 public static void main(String[] args) {
  try {
   System.out.println("I am Bharani Ravi Kanth R");
   System.out.println("My age is  " + 27);
   System.out.println("I Love Linux");
  } catch (ArithmeticException e) {
   System.out.println("My age is  " + 54 / 2);
  }
  System.out.println("I am a DevOp");
 }
}

in the above class, in the try block the risky code will  raise no exception in the run time, if there no exception then catch block will be not activated, the flow of execution would the lines inside of the risky code and the line of code which is after catch block.

lets run and see the code.

Output:
I am Bharani Ravi Kanth R
My age is  27
I Love Linux
I am a DevOp

Case 2: If there is an exception raised by the risky code, and catch block catching the same exception type
package com.learning.exceptionhandling;

public class SampleClass {

 public static void main(String[] args) {
  try {
   System.out.println("I am Bharani Ravi Kanth R");
   System.out.println("My age is  " + 27/0);
   System.out.println("I Love Linux");
  } catch (ArithmeticException e) {
   System.out.println("My age is  " + 54 / 2);
  }
  System.out.println("I am a DevOp");
 }
}

In the above class we can see that exception would be raised at the line
System.out.println("My age is  " + 27/0);
and type of the exception is raised is ArithmeticException, and catch block is matching it and handled code will be executed. so now the order of execution will be

1. Statement 1 will be executed which is below line of code, 
System.out.println("I am Bharani Ravi Kanth R");

2. While executing the statement 2,
System.out.println("My age is  " + 27/0);
An exception of type ArithmeticExcepion is raised and catch block is activated and the statement inside the catch block which is below will be executed.
System.out.println("My age is  " + 54 / 2);
3 Next execution control goes to the statement which is immediately outside the catch block. the statement
System.out.println("I am a DevOp");

4)The statement
System.out.println("I Lovee Linux");
will never be executed because, once the the control moves from try to catch the remaining statements after the statement which raised the issue will never be executed

Lets run the code,

Output:
I am Bharani Ravi Kanth R
My age is  27
I am a DevOp

you can see from the output  the statement below is completely ignored
System.out.println("I Love Linux");

Note: Its a good practice having the statements only the risky code inside the try block, so that the non risky code inside the try block will not be ignored after an exception  is raised. 


Case 3: If there is an exception raised by the risky code, and catch block is not handling the type of exception raised.
package com.learning.exceptionhandling;

public class SampleClass {

 public static void main(String[] args) {
  try {
   System.out.println("I am Bharani Ravi Kanth R");
   int[] ageArray = null;
   System.out.println("My age is  " + ageArray[0]);
   System.out.println("I Love Linux");
  } catch (ArithmeticException e) {
   System.out.println("My age is  " + 54 / 2);
  }
  System.out.println("I am a DevOp");
 }
}

In the above class, we can see the exception will raise at the statement below
System.out.println("My age is  " + ageArray[0]);
We trying to access an index of null array, so it will for sure raise NullPointerException.But the catch block is not handling NullPointerException but handling only ArithmeticException so in this the application will abnormally terminate when the exception is raised.

In the below case, only statement 1 which is below will be executed
System.out.println("I am Bharani Ravi Kanth R");
and then program will be terminated

Lets run the code,

Output:
I am Bharani Ravi Kanth R
Exception in thread "main" java.lang.NullPointerException
 at com.learning.exceptionhandling.SampleClass.main(SampleClass.java:9)

Case 4: If there is an exception raised by the risky code, and catch block catching the same exception type, but the handled code turned out to be risky.
package com.learning.exceptionhandling;

public class SampleClass {

 public static void main(String[] args) {
  try {
   System.out.println("I am Bharani Ravi Kanth R");
   System.out.println("My age is  " + 27 / 0);
   System.out.println("I Love Linux");
  } catch (ArithmeticException e) {
   System.out.println("My age is  " + 54 / 0);
  }
  System.out.println("I am a DevOp");
 }
}

In the above class, we can see the exception will raise at the statement below
System.out.println("My age is  " + 27 / 0);
The exception type is ArithmeticException and catch block is activated once the exception is raised but catch block is also having risky code which raises exception.
System.out.println("My age is  " + 54 / 0);
even the above statement will raise ArithmeticException. even in this case the code abnormally terminates when the statement in the catch block is executed.

In the below case, only statement 1 which is below will be executed
System.out.println("I am Bharani Ravi Kanth R");
and then program will be terminated

Lets run the code,

Output:

I am Bharani Ravi Kanth R
Exception in thread "main" java.lang.ArithmeticException: / by zero
 at com.learning.exceptionhandling.SampleClass.main(SampleClass.java:11)


Below are the control flow cases, so use the try/catch block smartly and keep the try block as small as possible.


Methods to print exception Information:

There are three methods where we can print the exception information,
1. printStackTrace()
2. getMessage()
3. toString()


Printing exception information by printStackTrace():
 If an exception is raised and if we want to print the exception details, Like Name of the Exception, cause of the exception, also the which line of code the exception is raised.  Then we have to go for printStackTrace() method

Lets take a simple class and print the exception when an exception is raised.

package com.learning.exceptionhandling;

public class SampleClass {

 public static void main(String[] args) {
  try {
   System.out.println("I am Bharani Ravi Kanth R");
   System.out.println("My age is  " + 27 / 0);
   System.out.println("I Love Linux");
  } catch (ArithmeticException e) {
   e.printStackTrace();
  }
 }
}

Output :

I am Bharani Ravi Kanth R
java.lang.ArithmeticException: / by zero
 at com.learning.exceptionhandling.SampleClass.main(SampleClass.java:8)

we can see  the output printStackTrace() method is printing the following

1. Name of the Exception 
java.lang.ArithmeticException
2. Reason for the exception
: / by zero
3. At what point the code the exception is raised
at com.learning.exceptionhandling.SampleClass.main(SampleClass.java:8)

Printing exception information by exception object reference or toString() Method:

 If an exception is raised and if we want to print the exception details, Like Name of the Exception, and cause of the exception and doesn't want to show in what point the exception is raised, then we will print the object reference or explicitly toString() Method of that exception object, if we are printing an object reference internally toString() method is called.

Lets take a simple class and print the exception with the exception object reference and toString method()

package com.learning.exceptionhandling;

public class SampleClass {

 public static void main(String[] args) {
  try {
   System.out.println("I am Bharani Ravi Kanth R");
   System.out.println("My age is  " + 27 / 0);
   System.out.println("I Love Linux");
  } catch (ArithmeticException e) {
   System.out.println(e);
   System.out.println(e.toString());
   
  }
 }
}

Output:
I am Bharani Ravi Kanth R
java.lang.ArithmeticException: / by zero
java.lang.ArithmeticException: / by zero

We can see the output  for printing the  exception object reference or toString() method.

1. Name of the exception
java.lang.ArithmeticException
2. Reason for the exception
: / by zero


Printing exception information using getMessage() Method:
 If an exception is raised and if we want to print the exception details, only reason of the exception,  Then we have to go for getMessage() method

Lets take a simple class and print the exception using getMessage() method.

package com.learning.exceptionhandling;

public class SampleClass {

 public static void main(String[] args) {
  try {
   System.out.println("I am Bharani Ravi Kanth R");
   System.out.println("My age is  " + 27 / 0);
   System.out.println("I Love Linux");
  } catch (ArithmeticException e) {
   System.out.println(e.getMessage());
   
  }
 }
}

Output:
I am Bharani Ravi Kanth R
/ by zero

We can see the output of getMessage() method above.

 Reason for the exception for the exception only printed.
/ by zero


Note: 
1. printStackTrace(),toString() and getMessage() can be used in any exception or error object as these are the methods of its root class Throwable.
2. printStackTrace() method will print the exception in the console.


try with multiple catch blocks:

We see in most of the cases, programmers use the following way to handle an exception as below

try
{
//risky code
}
catch(Exception e)
{
 //handle exception logic
}

Below format works but if we want to have  different handle code logic on different exceptions then
 using catch block as below is not valid.

catch(Exception e)
{
 //handle exception logic
}  

lets take a sample java class and will see how multiple catch blocks works.


package com.learning.exceptionhandling;

public class SampleClass {

 public static void main(String[] args) {
  try {
   System.out.println("I am Bharani Ravi Kanth R");
   System.out.println("My age is  " + 27 / 0);
  } catch (NullPointerException e) {
   System.out.println("This is null pointer exception catch block : "+e.getMessage());

  } catch (ArithmeticException e) {
   System.out.println("This is Arithmetic exception catch block : "+e.getMessage());
  }

 }
}

We can see in different blocks we are performing different tasks, Now when we run the code and exception is raised, JVM picks the exception checks the catch block from top to bottom whether that catch block can handle the exception.

In the present example type of exception raised is ArithmeticException, when the exception is raised the controls goes to the first catch block, but the current catch block can handle only null pointer exception, Now the control comes out and checks the other catch block,Now the second catch block can catch ArithmeticException, the second catch block will be activated and run the executes the statements which is inside that catch block. 

Lets run the code.

Output:

I am Bharani Ravi Kanth R
This is Arithmetic exception catch block : / by zero


Rules of multiple catch block is:

1. Order of the catch block should be mandatory, i.e, first child classes of exceptions are used then the parent class and not the vice versa.

for example, below is the valid example

try
{
Risky Code
}
catch(NullPointerException e)
{
}
catch(Exception e)
{
}

below is not valid, because parent class Exception can handle even NullPointerException, So the null pointer exception catch block is never called.

try
{
Risky Code
}
catch(Exception e)
{
}
catch(NullPointerException e)
{
}

2. There cannot be two catch blocks with same exceptions type.

try
{
Risky Code
}
catch(NullPointerException e)
{
}
catch(NullPointerException e)
{
}

above usage of is not valid because, once the NullPointerException catch block is executed the control moves out the catch area, so the next block will be never called.



Exception Handling - Checked Vs Unchecked Exceptions

Exception Handling - Checked Vs Unchecked Exceptions
There are two types of Exceptions

1. Checked Exceptions
2. Unchecked Exceptions

Checked Exceptions : These are the type of exceptions which are raised by the compiler for smooth execution of the code in the run time.

Lets take a simple real time scenario between Mother,Son and Lunch Box.

1. When the child is leaving to school, Mother asks the Son whether he has taken the lunch box with him,
 2. Son Checks his bag and tell his mother that he has taken the lunch box.

Here, The mother is checking the child because, if the he forget his lunch box, he would miss the meal at the lunch break.

If we represent it in java.

Mother - Java Compiler.
Student - Is the application.
Lunch Box - Is the parameter checked by the compiler, which may cause an issue.

Lets do a simple example, for Better understanding do not use an IDE for this example. 
package com.learning.exceptionhandling;

import java.io.PrintWriter;

public class SampleClass {

 public static void main(String[] args) {
  PrintWriter printWriter=new PrintWriter("c:/Sample.txt");
  printWriter.write("I am Bharani Ravi Kanth R");
 }
}

I am trying to print a text "I am Bharani Ravi Kanth R" to a file called Sample.txt. lets try compiling the code through command line.

C:\com\learning\exceptionhandling>javac SampleClass.java
SampleClass.java:8: error: unreported exception FileNotFoundException; must be caught or declared to be thrown
                PrintWriter printWriter=new PrintWriter("c:/Sample.txt");
                                        ^
1 error

Here its not an issue with the application, but compiler is helping us to be cautious, What if the file you are trying to access doesn't exist at all. So the compiler is giving us the below message

unreported exception FileNotFoundException; must be caught or declared to be thrown
i.e, handle the code if the file we are trying to access doesn't exist.

There are two ways we can handle the checked exceptions,
1. try catch block.
2. throws keyword.

So in the above example, we can handle the code as below so that compiler compiles our code properly.

try catch block:

package com.learning.exceptionhandling;

import java.io.FileNotFoundException;
import java.io.PrintWriter;

public class SampleClass {

 public static void main(String[] args) {
  try {
   PrintWriter printWriter = new PrintWriter("c:/Sample.txt");
   printWriter.write("I am Bharani Ravi Kanth R");
  } catch (FileNotFoundException e) {
   e.printStackTrace();
  }
 }
}

throws keyword:

package com.learning.exceptionhandling;

import java.io.FileNotFoundException;
import java.io.PrintWriter;

public class SampleClass {

 public static void main(String[] args) throws FileNotFoundException {
   PrintWriter printWriter = new PrintWriter("c:/Sample.txt");
   printWriter.write("I am Bharani Ravi Kanth R");
 }
}

Now let us compile the code.

C:\com\learning\exceptionhandling>javac SampleClass.java

C:\com\learning\exceptionhandling>

We can see now that compiler has no issues compiling the code.

Checked Exceptions are checked in two ways

1. Fully Checked: We need to check both parent and child,
2. Partial Checked: If we check only the parent not its child classes.


Note: Only possible partial checked exceptions classes in java are Throwable and Exception.


Unchecked Exceptions: The exceptions which are caused by the application, mostly at runtime,
Unchecked Exceptions are mostly

1. Errors
2. Runtime Exceptions.

Unchecked Exceptions - Error:  we are trying to run the application in the server, but the application couldn't start up because of OutOfMemory error, that is application is not having enough heap space to run. here its not the application which caused the issue, but the server doesn't have enough system resources to run the application.

Unchecked Exceptions - Runtime Exceptions: These are the exceptions which are caused by the applications at runtime, like dividing an integer by zero this causes ArithmeticException, trying to access an object which was never initialized causes null pointer exception.


Lets see a simple example, we are trying to fetch an value from an string array object which never initialized

package com.learning.exceptionhandling;

public class SampleClass {

 public static void main(String[] args) {

  String[] stringArray=null;
  System.out.println(stringArray[0]);
 }
}

Output:
Exception in thread "main" java.lang.NullPointerException
 at com.learning.exceptionhandling.SampleClass.main(SampleClass.java:8)


Note: Runtime exceptions are not found by the compiler while compiling our source code.