avatarMouad Oumous

Summary

The webpage content provides an in-depth explanation of rethrowing exceptions in Java, including practical examples, the importance of updating stack traces, and the distinction between rethrowing the same or a new exception.

Abstract

The article on the undefined website delves into the concept of rethrowing exceptions in Java, a technique used when a caught exception in a try block needs to be thrown again. It explains that rethrowing an exception allows for additional handling or logging within the catch block before propagating the exception to a higher context. The article emphasizes the preservation of the exception object's information during rethrowing and illustrates how to update the stack trace using fillInStackTrace() to reflect the point of rethrowing. It also explores the scenario of throwing a different exception type, thereby losing the original exception's context. The discussion includes the distinction between the keywords throw, throws, and the Throwable class, clarifying their roles in Java's exception handling mechanism. The article aims to enhance the reader's understanding of exception handling, which is crucial for writing robust Java code.

Opinions

  • The author suggests that understanding how to handle exceptions is key to creating high-quality Java code.
  • It is implied that rethrowing exceptions with fillInStackTrace() is a useful technique for accurately pinpointing the location of a rethrown exception.
  • The article conveys that rethrowing a new exception can be appropriate in certain scenarios, but it also highlights the loss of the original exception's context that comes with this approach.
  • The author encourages readers to join a WhatsApp group and a Telegram channel for further discussion and learning about Java, indicating a community-oriented approach to education.
  • There is an underlying emphasis on the importance of proper exception handling to avoid semantic errors and ensure that Java programs behave as expected.

Rethrowing An Exception In Java | Exception Handling

Rethrowing An Exception In Java | Exception Handling

JOIN US ON WHATSAPP

An exception that is caught in the try block can be thrown once again and can be handled. The try block just above the rethrow statement will catch the rethrown object. If there is no try block just above the rethrow statement then the method containing the rethrow statement handles it. To propagate an exception, the catch block can choose to rethrow the exception by using the throw statement. Note that there is no special syntax for rethrowing.

· Sample Example : Rethrowing An Exception · Program · Update stack trace before rethrowing · Rethrowing a new exception

Sample Example : Rethrowing An Exception

Since you already have the reference to the current exception, you can simply rethrow that reference:

catch(Exception e) { 
System.out.println("An exception was thrown"); 
throw e; 
}

Normally, catch block are used to handle the exceptions raised in the try block. An exception can be rethrown in a catch block using throw keyword, if catch block is unable to handle it. This process is called as re-throwing an exception.

Rethrowing an exception causes it to go to the exception handlers in the nexthigher context. Any further catch clauses for the same try block are still ignored. In addition, everything about the exception object is preserved, so the handler at the higher context that catches the specific exception type can extract all the information from that object. If the handler is not exist then this action will cause the exception to be passed to the calling method. If the rethrow operation occurs in the main method then the exception is passed to the JVM and displayed on the console.

The purpose of the rethrow operation is to get the attention of the outside world that an exception has occurred and at the same time perform any contingency logic (such as logging) in the catch block.

Program

public class Main {
 
   public int test(int n1, int n2) {
     try{
           return n1/n2;
      }catch(ArithmeticException e){
         throw e; 
      }
   }
 
   public static void main(String[] args) {
      Main main = new Main();
      try{
          System.out.println(main.test(30, 0));
      }catch(Exception e){
          e.printStackTrace();
      }
   }
 
}

Output

java.lang.ArithmeticException: / by zero
        at Main.test(Main.java:5)
        at Main.main(Main.java:14)

Update stack trace before rethrowing

If you simply rethrow the current exception, the information that you print about that exception in printStackTrace( ) will pertain to the exception’s origin, not the place where you rethrow it. If you want to install new stack trace information, you can do so by calling fillInStackTrace( ), which returns a Throwable object that it creates by stuffing the current stack information into the old exception object. Here’s what it looks like:

//: exceptions/Rethrowing.java 
// Demonstrating fillInStackTrace() 
public class Rethrowing { 
 public static void f() throws Exception { 
 System.out.println("originating the exception in f()"); 
 throw new Exception("thrown from f()"); 
 } 
 public static void g() throws Exception { 
 try { 
   f(); 
 } catch(Exception e) { 
   System.out.println("Inside g(),e.printStackTrace()"); 
   e.printStackTrace(System.out); 
   throw e; 
 } 
 } 
 public static void h() throws Exception {
  try { 
   f(); 
 } catch(Exception e) { 
   System.out.println("Inside h(),e.printStackTrace()"); 
   e.printStackTrace(System.out); 
   throw (Exception)e.fillInStackTrace(); 
 } 
 } 
 public static void main(String[] args) { 
 try { 
     g(); 
 } catch(Exception e) { 
     System.out.println("main: printStackTrace()"); 
     e.printStackTrace(System.out); 
 } 
 try { 
     h(); 
 } catch(Exception e) { 
     System.out.println("main: printStackTrace()"); 
     e.printStackTrace(System.out); 
 } 
 } 
}

Output

originating the exception in f() 
Inside g(),e.printStackTrace() 
java.lang.Exception: thrown from f() 
     at Rethrowing.f(Rethrowing.java:7) 
     at Rethrowing.g(Rethrowing.java:11) 
     at Rethrowing.main(Rethrowing.java:29) 
main: printStackTrace() 
java.lang.Exception: thrown from f() 
     at Rethrowing.f(Rethrowing.java:7) 
     at Rethrowing.g(Rethrowing.java:11) 
     at Rethrowing.main(Rethrowing.java:29) 
originating the exception in f() 
Inside h(),e.printStackTrace() 
java.lang.Exception: thrown from f() 
     at Rethrowing.f(Rethrowing.java:7) 
     at Rethrowing.h(Rethrowing.java:20) 
     at Rethrowing.main(Rethrowing.java:35) 
main: printStackTrace() 
java.lang.Exception: thrown from f() 
     at Rethrowing.h(Rethrowing.java:24) 
     at Rethrowing.main(Rethrowing.java:35) 
*///:~

The line where fillInStackTrace( ) is called becomes the new point of origin of the exception.

Rethrowing a new exception

It’s also possible to rethrow a different exception from the one you caught. If you do this, you get a similar effect as when you use fillInStackTrace( ) — the information about the original site of the exception is lost, and what you’re left with is the information pertaining to the new throw:

//: exceptions/RethrowNew.java 
// Rethrow a different object from the one that was caught. 
class OneException extends Exception { 
 public OneException(String s) { super(s); } 
} 
class TwoException extends Exception {
 public TwoException(String s) { super(s); } 
} 
public class RethrowNew { 
 public static void f() throws OneException { 
 System.out.println("originating the exception in f()"); 
 throw new OneException("thrown from f()"); 
 } 
 public static void main(String[] args) { 
 try { 
 try { 
   f(); 
 } catch(OneException e) { 
   System.out.println( 
   "Caught in inner try, e.printStackTrace()"); 
   e.printStackTrace(System.out); 
   throw new TwoException("from inner try"); 
 } 
 } catch(TwoException e) { 
   System.out.println( 
   "Caught in outer try, e.printStackTrace()"); 
   e.printStackTrace(System.out); 
 } 
 } 
}

Output

originating the exception in f() 
Caught in inner try, e.printStackTrace() 
OneException: thrown from f() 
   at RethrowNew.f(RethrowNew.java:15) 
   at RethrowNew.main(RethrowNew.java:20) 
Caught in outer try, e.printStackTrace() 
TwoException: from inner try 
   at RethrowNew.main(RethrowNew.java:25) 
*///:~

The final exception knows only that it came from the inner try block and not from f( ).

You never have to worry about cleaning up the previous exception, or any exceptions for that matter. They’re all heap-based objects created with new, so the garbage collector automatically cleans them all up.

Often first-time readers may get confused about the use of the three keywords: throw, throws and Throwable. It is therefore useful to dwell on the three concepts together in order to clarify their meaning.

Throwable is a class. Though the Throwable class is derived from the java.lang.Object class in the Java class library, Throwable is the super-class of all classes that handle exceptions.

The keyword throw is a statement that throws an exception. Note that an exception can be thrown either by the throw statement or when an error occurs during the execution of any other statement.

The keyword throws is a clause specified in the method definition which indicates that the method throws the exceptions mentioned after the keyword throws, which are handled in the called methods.

Happy learning 😃

Join Mouad Oumous Java WhatsApp Group JOIN

Join Mouad Oumous Telegram Channel JOIN

Programming
Coding
Java
Java Tutorial
Exception Handling
Recommended from ReadMedium