Nested exception example in java

Tech Tutorials

Tutorials and posts about Java, Spring, Hadoop and many more. Java code examples and interview questions. Spring code examples.

Thursday, August 12, 2021

Nested Try Statements in Java Exception Handling

A try-catch-finally block can reside inside another try-catch-finally block that is known as nested try statement in Java.

When you have nested try statements in your code, in case an exception is thrown the inner most try-catch block gets the first chance to handle that exception, if that try-catch block can not handle the exception, the exception goes up the hierarchy (next try-catch block in the stack) and the next try statement’s catch block handlers are inspected for a match. If no catch block, with in the hierarchy, handles the thrown exception then the Java run-time system will handle the exception.

Java nested try statement example

public class NestedTryDemo < public static void main(String[] args) < try< System.out.println("In Outer try block"); try< System.out.println("In Inner try block"); int a = 7 / 0; >catch (IllegalArgumentException e) < System.out.println("IllegalArgumentException caught"); >finally < System.out.println("In Inner finally"); >>catch (ArithmeticException e) < System.out.println("ArithmeticException caught"); >finally < System.out.println("In Outer finally"); >> >
In Outer try block In Inner try block In Inner finally ArithmeticException caught In Outer finally

In this example, one try catch finally sequence has been nested within another try catch finally sequence. The inner try block throws an ArithmeticException which it could not handle, as the inner catch block catches IllegalArgumentException. Hence, this exception moves up the hierarchy and handled in the outer try-catch-finally block.

Читайте также:  Adobe reader pdf to html

Better way to use nested try statement

In the above example you have seen how exception propagates and can be handled by the inner or outer block based on which catch block can handle it. But the better way to design nested try statements in Java exception handling is to look for the code sections which are more likely to throw any specific exception and wrap those specific blocks in a try-catch block that can handle that exception and overall code can be wrapped in more general try-catch block.

Java nested try statement example

Let’s change the above code a little bit, now there is a method with an int as argument. That argument is used to divide 7 in the code. You also have a condition that passed argument should be less than or equal to 7 otherwise IllegalArgumentException must be thrown.

Also you need to check for divide by zero condition in which case you must handle ArithmeticException. Overall you may have a try-catch block which can handle any other exception.

To handle this scenario you may start a try block in which you can check if the passed value is less than or equal to 7 or not, if not throw IllegalArgumentException and then have a nested try-catch where you can handle ArithmeticException. After that you can have a catch block for the outer try statement to handle IllegalArgumentException.

So overall there are three try-catch blocks with in the code. One outer try-catch statement and two nested try statement with in it for handling specific exceptions.

public class NestedTryDemo < public static void main(String[] args) < NestedTryDemo nd = new NestedTryDemo(); nd.process(8); >private void process(int num) < try< try< if(num >7) < throw new IllegalArgumentException("Number should not be greater than 7"); >try< System.out.println("In Inner try block"); int a = 7 / num; System.out.println("value of a " + a); >catch (ArithmeticException e) < System.out.println("ArithmeticException caught - " + e.getMessage()); >>catch(IllegalArgumentException e) < System.out.println("IllegalArgumentException caught - " + e.getMessage()); >>catch(Exception exp)< System.out.println("Exception in the code " + exp.getMessage()); >finally < System.out.println("In Outer finally"); >> >
IllegalArgumentException caught - Number should not be greater than 7 In Outer finally

If you execute the same code by passing 0, then the output will be-

In Inner try block ArithmeticException caught - / by zero In Outer finally

If you execute the same code by passing 3, then the output will be

In Inner try block value of a 2 In Outer finally

That’s all for this topic Nested Try Statements in Java Exception Handling. If you have any doubt or any suggestions to make please drop a comment. Thanks!

Источник

Java Nested Exceptions

An interesting point to consider related to the last example is what will happen if the logError() invocation causes an exception to be thrown, since that invocation occurs inside the catch block that handles a different exception.

In practice, of course, logging doesn’t generally cause exceptions, but it’s worthwhile to consider what would happen if one did occur.

With the code in its current state the original exception generated by doSomething() would effectively be discarded and the one generated by logError() would be thrown.

Discarding the original exception obviously isn’t ideal, and in fact it’s not substantially different from the code shown earlier with the empty catch block that caught the exception from doSomething() and ignored it.

Again, this is very undesirable behavior, but having two exceptions does present something of a problem, because Java doesn’t support the ability to throw two different exceptions from a single method invocation-at least not directly.

The best solution to this is to use exception nesting, where one exception is essentially wrapped by another, and the original or «inner» exception is said to be the «cause» of the second «outer» exception.

In this scenario the inner exception is the one generated by doSomething() while the outer exception is the one generated by logError().

Support for exception nesting is built in to the exception facility, with the Exception class (and most of its subclasses) defining constructors that accept both a message like the ones we’ve been creating and also a reference to an inner exception to be wrapped.

We can take advantage of this design by putting the call to logError() inside its own try/catch block, and creating and throwing a new exception that encapsulates both the original exception and the one generated by the logError() call.

resourceLock.lock(); try < doSomething(); >catch (Exception e) < try < logError(«An error occurred calling doFinally()»); > catch (Exception le) < throw new LoggingException( «An error occurred during logging: « + le.getMessage(), le); > throw e; > finally

As mentioned before, we don’t want to just ignore the original exception from doSomething() but want to wrap it in our custom exception class, so we’ll implement a constructor that accepts a reference to the original exception and maintains a reference to it as shown here.

public class LoggingException extends Exception < public LoggingException(String message, Exception cause) < super(message, cause); > >

When the LoggingException is thrown, the caller can retrieve information on both exceptions: the Exception that occurred when attempting to create the log message and the original exception generated by doSomething().

Accessing the original exception is done by calling the getCause() method defined in the Throwable class and inherited by Exception and its subclasses.

demo2s.com | Email: | Demo Source and Support. All rights reserved.

Источник

Nesting Exceptions

75% developed

When an exception is caught, the exception contains the stack-trace, which describes the error and shows where the exception happened (i.e. where the problem is and where the application programmer should look to fix the problem). Sometimes it is desirable to catch an exception and throw another exception. If the new exception keeps a reference to the first exception, the first exception is called a nesting exception.

public class NestingExceptionExample < public static void main(String[] args) throws Exception < Object[] localArgs = (Object[]) args; try < Integer[] numbers = (Integer[]) localArgs; >catch (ClassCastException originalException) < Exception generalException = new Exception( "Horrible exception!", originalException); throw generalException; >> >
Exception in thread "main" java.lang.Exception: Horrible exception! at NestingExceptionExample.main(NestingExceptionExample.java:9) Caused by: java.lang.ClassCastException: [Ljava.lang.String; incompatible with [Ljava.lang.Integer; at NestingExceptionExample.main(NestingExceptionExample.java:7)

The above code is an example of a nesting exception. When the Exception is thrown, by passing in the ClassCastException object reference as a parameter, the ClassCastException is nested in the newly created Exception , its stack-trace is appended together. When the Exception is caught, its stack-trace contains the original ClassCastException ‘s stack-trace.

This is a kind of exception conversion, from one exception to another. For example, calling a remote object using RMI, the calling method has to deal with RemoteException which is thrown if something is wrong during the communication. From the application point of view, RemoteException has no meaning, it should be transparent to the application that a remote object was used or not. So the RemoteException should be converted to an application exception.

This conversion can also hide where the error is originated. The stack-trace starts when the exception is thrown. So when we catch and throw a new exception, the stack-trace starts at when the new exception was thrown, losing the original stack-trace. This was true with the earlier version of Java (before 1.4). Since then, so called cause facility capabilities were built in the Throwable class.

A throwable contains a snapshot of the execution stack of its thread at the time it was created. It can also contain a message string that gives more information about the error. Finally, it can contain a cause: another throwable that caused this throwable to get thrown. The cause facility is also known as the chained exception facility, as the cause can, itself, have a cause, and so on, leading to a «chain» of exceptions, each caused by another.

A cause can be associated with a throwable in two ways: via a constructor that takes the cause as an argument, or via the initCause(Throwable) method. New throwable classes that wish to allow causes to be associated with them should provide constructors that take a cause and delegate (perhaps indirectly) to one of the Throwable constructors that takes a cause. For example:

try < lowLevelOp(); >catch (LowLevelException le)

Because the initCause method is public, it allows a cause to be associated with any throwable, even a «legacy throwable» whose implementation predates the addition of the exception chaining mechanism to Throwable. For example:

try < lowLevelOp(); >catch (LowLevelException le)

Further, as of release 1.4, many general purpose Throwable classes (for example Exception , RuntimeException , Error ) have been retrofitted with constructors that take a cause. This was not strictly necessary, due to the existence of the initCause method, but it is more convenient and expressive to delegate to a constructor that takes a cause.

By convention, class Throwable and its subclasses have two constructors, one that takes no arguments and one that takes a String argument that can be used to produce a detail message. Further, those subclasses that might likely have a cause associated with them should have two more constructors, one that takes a Throwable (the cause), and one that takes a String (the detail message) and a Throwable (the cause).

To do:
Add some exercises like the ones in Variables

Источник

Оцените статью