This is the second post on a series of Exception Handling in Java. In this article, we will learn methods to print exception info, try with multiple catch blocks, finally block and most important difference between final, finally, finalize. Before starting these, please go through Exception Handling in Java | Part-1 so that you clear with the basics of Exception Handling.
Methods to print exception information :
Thowable class defines following methods to print exception information:
printStackTrace() - Name of exception : Description StackTrace
toString() - Name of exception : Description
getMessage() - Description
Method printable format
For example :
class Test{ public static void main(String[] args){ try{ sop(10/0); }catch(AE ae){ sop(e.getMessge()) // "/ by zero" sop(e.toString()); // "java.lang.AE : / by zero" sop(e.printStackTrace()); // "java.lang.AE : / by zero at Test.main()" } } }
Note : Internally default exception handler will use the printStrackTrace() to print exception information to console.
Try with multiple catch blocks
The way of handling an exception is varied from exception to exception. Hence for every exception type, it is highly recommended to take a separate catch block i.e. try with multiple catch blocks.
Worst programming practice :
try{ //riskey code }catch(Exception e){ }
Best programming practice: use multiple catch blocks
try{ //riskey code }catch(ArithmeticException e){ }catch(SQLException e e){ }catch(FileNotFoundException e){ }catch(Exception e){ //Defaullt exception }
Note :
If try with multiple catch block is present then the order of catch block is very important.
We have to take the child first then the parent otherwise we will get a compile-time error saying Exception xxx has already been caught.
We can't declare two catch blocks for the same exception otherwise we will get a compile-time error.
Difference between final, finally, finalize
final :
final is modifier applicable for classes, methods, and variables
If the class is declared as final then we can't extend that class i.e. Inheritance is not possible for final classes
If a method is final then we can't use that method in the child class
If a variable is declared as final then we can't reassignment for that variable
finally():
try{ // riskey code }catch(Exception e){ // handler code }finally{ // clean-up code }
The specialty of the finally block is it will be executed always irrespective of whether an exception is raised or not, handled, or not handled.
finalize():
It is a method always invoked by garbage collector just before destroying an object to perform cleanup activities.
once the finalize method completes immediately garbage collector destroys that object.
Note :
finally block is responsible to perform clean up activity related to try block i.e. whatever resources as a part of try block will be closed inside finally block whereas the finalize method is responsible to perform clean up activity related to object i.e. whatever resources associated with the object will be deallocated by using finalize method
Various possible combinations of try-catch-finally
Note :
In try-catch-finally order is very important
try without a catch or finally is invalid otherwise Compile Time Error: try without a catch or finally is invalid
Whenever we are writing catch block compulsory try block is required... try without a catch is invalid
finally without try is invalid
Inside try-catch and finally block we can declare try-catch and finally block i.e. nesting of try-catch-finally is allowed
For try-catch and finally block curly bases are mandatory
throw in Java
Sometimes we can create exception objects explicitly and handover to JVM manually for these we have to use the throw keyword.
For e.g. throw new AE("/ by zero")
The main objective of throw keyword is handover our created exception object to the JVM manually
Hence the result of the following two programs are the same:
The main method is responsible to create the exception object and handover to JVM:
public class Test1{ public static void main(String[] args) { System.out.println(10/0); } } o/p: Exception in thread "main" java.lang.ArithmeticException: / by zero at ExceptionHandling.Test1.main(Test1.java:3)
Here Programmer creating exception object explicitly and handover to JVM manually
public class Test1{ public static void main(String[] args) { throw new ArithmeticException("Divide by zero"); } } o/p: Exception in thread "main" java.lang.ArithmeticException: / by zero at ExceptionHandling.Test1.main(Test1.java:3)
The best use of the throw keyword is for user-defined exceptions.
Let's see some interesting example of custom exceptions:
Case 1: throw e, if e refers null then we will get NPE
public class Test1{ static ArithmeticException e = new ArithmeticException(); public static void main(String[] args) { throw e; } } o/p: Exception in thread "main" java.lang.ArithmeticException at ExceptionHandling.Test1(Test1.java:2)
public class Test1{ static ArithmeticException e; public static void main(String[] args) { throw e; } } o/p: Exception in thread "main" java.lang.NullPointerException at ExceptionHandling.Test1.main(Test1.java:4)
Case 2: After throw statement, we are not allowed to write any statement directly otherwise we will get compile-time error unreachable statement
public class Test1 { public static void main(String[] args) { throw new ArithmeticException("/ by zero"); System.out.println("print hello"); } } o/p : Compile Time Error:(7, 9) java: unreachable statement
public class Test1 { public static void main(String[] args) { System.out.println(10/0); System.out.println("print hello"); } } o/p: Run time Exception in thread "main" java.lang.ArithmeticException: / by zero at ExceptionHandling.Test1.main(Test1.java:5)
Case 3: We can use the throw keyword only for throwable type if we are trying for a normal java object then we will get a compile-time error saying incompatible types.
public class Test1 { public static void main(String[] args) { throw new Test1(); } } o/p: Error:(5, 9) java: incompatible types: ExceptionHandling.Test1 cannot be converted to java.lang.Throwable
public class Test1 extends ArithmeticException{ public static void main(String[] args) { throw new Test1(); } } o/p: Exception in thread "main" ExceptionHandling.Test1 at ExceptionHandling.Test1.main(Test1.java:5)
throws in Java
In our program if there is a possibility of raising checked exception then compulsory we should handle it, otherwise we will get a compile-time error: Unreported exception java.io.FileNotFoundException; must be caught or declared to be thrown
public class Test1{ public static void main(String[] args) { PrintWriter pw = new PrintWriter("abc.txt"); pw.write("a"); } } o/p: Unreported exception java.io.FileNotFoundException; must be caught or declared to be thrown
We can handle this compile-time error by using two ways:
By using try-catch
By using throws
public class Test1{ public static void main(String[] args) throws InterruptedException { Thread.sleep(1000); } }
Note:
We can use the throws keyword to delegate the responsibility of exception handling to the caller(JVM/method) then the caller is responsible to handle the exception
It is used for only checked exceptions
Usage of throws keyword doesn't prevent abnormal termination of a program
public class Test1{ public static void main(String[] args) throws InterruptedException { doMoreStuff(); } public void doMoreStuff() throws InterruptedException { doStuff(); } public void doStuff() throws InterruptedException { Thread.sleep(1000); } }
In the above program, if we removed at least one throws statement then our program won't compile
Use of throws
We can use the throws keyword for method and constructor but not for classes.
Class Test1 throws Exception - Invalid
Test1() throws Exception - Valid
public static void main(String[] args)throws Exception { - validWe can use throws keyword only for throwable types otherwise we will get a compile-time error - incompatible type
Within try block if there is no chance of raising an exception, we can't write a catch block for that exception otherwise we will get a compile-time error saying Exception xxx is never thrown in body of corresponding try statement, but this rule is applicable for only fully checked exceptions
public class Test1{ public static void main(String[] args){ try { Thread.sleep(1000); }catch (SQLException e){ System.out.println("sql exception"); } } } o/p: Error:(5, 6) java: exception java.sql.SQLException is never thrown in body of corresponding try statement Error:(4, 25) java: unreported exception java.lang.InterruptedException; must be caught or declared to be thrown
Lets quick summarise what we learn in this post:
Methods to print exception information
How to use try with multiple catch blocks
Difference between final, finally, finalize
Various possible combinations of try-catch-finally
throw keyword
throws keyword
With this, we also came to the end of this article. In the next article, we would be revising and learning Exception handling keywords summary, Various possible compile-time errors in exception handling, Customized or user-defined exceptions, etc.. Please let us know about your views and opinions in the comment section below. I hope you enjoyed these posts. Please stay with us for more posts.
For more details on exception handling please refer Video
0 comments:
Post a Comment