How does exception chain work in my code? - java

Why this code doesn't print "d". Why it doesn't go to the catch block for RunTimeException?
public static void main(String[] args) {
System.out.println("a");
try {
System.out.println("b");
throw new IllegalArgumentException();
} catch (IllegalArgumentException e) {
System.out.println("c");
throw new RuntimeException();
}catch (RuntimeException e) {
System.out.println("d");
throw new RuntimeException();
}finally{
System.out.println("e");
throw new RuntimeException();
}
}
The output of this program is
a
b
c
e
Exception in thread "main" java.lang.RuntimeException
EDIT: After throwing IllegalArgumentException it goes to the corresponding catch block and prints 'c'. after that since we don't catch the exception in RuntimeException it doesn't go any further. but since it's guranteed that we go to the finally block it print 'e' and after that throw RunttimeException. if the code was like something like the following, it would throw out the RuntimeException("2"). If we comment the exception inside finally, it throw out RuntimeException("1").
public static void main(String[] args) throws InterruptedException {
System.out.println("a");
try {
System.out.println("b");
throw new IllegalArgumentException();
} catch (IllegalArgumentException e) {
System.out.println("c");
throw new RuntimeException("1");
}catch (RuntimeException e) {
System.out.println("d");
throw new RuntimeException();
}finally{
System.out.println("e");
throw new RuntimeException("2");
}
}

The reason of this code not printing d is, because in the IllegalArgumentException catch block, after printing "c" and before throwing RuntimeException it executes finally (that's how the flow works). Finally block throws exception itself, so It never gets to throw that RuntimeException that gets it to "d".
public static void main(String[] args) {
System.out.println("a");
try {
System.out.println("b"); // 1
throw new IllegalArgumentException(); // 2
} catch (IllegalArgumentException e) {
System.out.println("c"); // 3
throw new RuntimeException(); // nope, there's a finally block that executes first
}catch (RuntimeException e) {
System.out.println("d");
throw new RuntimeException();
}finally{
System.out.println("e"); // 4
throw new RuntimeException(); // 5 - rest of the code never got executed.
}
}
Hope this was clear enough.
Also, as it was pointed out, even if the RuntimeException after "c" was executed, It would not invoke the lower catch block. The catch block is only invoked once, depending on the Exception thrown in the try block (though this isn't really relevant because the first explanation dictates the flow of your thread).

The catch blocks are NOT in the scope of the try. Any code in the catch blocks executes in the context of the outer main code, and thus has no exception handlers. When you throw RuntimeException the finally block for the try gets executed and then the exception terminates the program.

In try catch block, if one of the catch block catches the exception the other catches doesn't get involved. remeber that finally block always run at the end no matter exception gets threw or not.

Related

Why RuntimeException is not caught in catch block if there are multiple catch blocks?

I am able to catch RuntimeException or subclass of it with below code:
try {
//code that throws subclass of RuntimeException
throw new ChildRuntimeException("try");
} catch (Exception ex) {
System.out.println(ex.getMessage());
}
But I am getting error with below code and not able to catch RuntimeException in Exception catch block.
try {
// code that throws subclass of Exception
throw new ChildExceptionClass("try");
} catch (ChildExceptionClass ex) {
throw new RuntimeException(ex.getMessage());
} catch (Exception ex) {
System.out.println(ex.getMessage());
}
I searched for the same type of questions but did not find a suitable answer. Can
anyone explain why the behaviour is different?
In the second example you are throwing a childRuntimeException, which is caught, but then a new runtimeException is thrown. This block has no "catch" clause, so the exception is thrown and not caught.
The second catch is relevant for the "try" block, not for the "catch" block.
What I guess you probably want to do is:
try { // code that throws subclass of Exception
throw new ChildExceptionClass("try");
} catch (ChildExceptionClass ex) {
try {
throw new RuntimeException(ex.getMessage());
} catch (Exception ex) {
System.out.println(ex.getMessage());
}
}
Do you understand the difference?

Compiler forces to handle rethrow of unchecked exception

I have encountered a scenario while working with exceptions, following is the sample code.I am trying to understand why following code fails to compile. I am checking the exception type before rethrow which is unchecked exception.
public class TestException {
public void test() throws FileNotFoundException {
FileReader test = new FileReader("");
}
public static void main(String[] args){
TestException test=new TestException();
try {
test.test();
} catch (Exception e) {
// TODO Auto-generated catch block
if(e instanceof ArithmeticException){
throw e;
}
else{
e.printStackTrace();
}
}
}
}
You are still throwing a reference variable e of type Exception. Exception is a checked type. The compiler only knows the reference variable's type, not the referenced object's. If you want to keep main's method signature as-is, you'll need to either wrap e into an unchecked exception type (such as ArithmeticException):
if(e instanceof ArithmeticException){
throw new ArithmeticException(e.getMessage());
}
or cast it as an unchecked exception:
if(e instanceof ArithmeticException){
throw (ArithmeticException)e;
}
Since the reference variable e is of type java.lang.Exception, throw e will throw checked exception. Thus it has to be declared in throws section in the method signature.
Try changing your catch block as follows:-
if(e instanceof ArithmeticException){
throw (ArithmeticException)e;
}
else{
e.printStackTrace();
}
You could also use a hack with Generics to throw an checked Exception as an unchecked one:
http://www.gamlor.info/wordpress/2010/02/throwing-checked-excpetions-like-unchecked-exceptions-in-java/
I like to use this over throw new RuntimeException(e), since the latter creates unnecessary output in a Stacktrace and its harder to catch somewhere else (you have to check the cause instead of the excetion itself).
catch (Exception e) {
Here is the effective declaration of e.
if(e instanceof ArithmeticException){
Here you are doing a runtime check of the type of e.
throw e;
At this point the compile-time type of e is Exception. So the compiler enforces its rules.
I will suggest to use two catch blocks.
typechecking in catch block is not a good practice where you can catch that specific class using other catch statement.
catch (ArithmeticException e) {
// TODO Auto-generated catch block
throw e;
}
catch(Exception e)
{
e.printStackTrace();
}
#Silly Freak I agree with you.
If you throw any exception then you should handle it but in your program your are able to throw but nowhere you are handling the exception, so just handle the exception by adding throws in main class like this:-
package first;
import java.io.FileNotFoundException;
import java.io.FileReader;
class A3{
public void test() throws FileNotFoundException {
FileReader test = new FileReader("");
}
public static void main(String[] args) throws Exception{
A3 test=new A3();
try {
test.test();
} catch (Exception e) {
// TODO Auto-generated catch block
if(e instanceof ArithmeticException){
throw e;
}
else{
e.printStackTrace();
}
}
}
}

Catch exceptions without a try block?

I have a lot of custom exceptions that I'm throwing in a specific cases in the code, and I'd like to have one catch block at the bottom of the method to handle them all.
All the exceptions are children of the Exception class CribbageException, so I'd like to have:
public void myMethod(){
if (whatever){
throw new CardException();
}
if (something else){
throw new InvalidCardException();
}
if (scenario 3){
throw new TwoCardsException();
}
catch (CribbageException e) {
System.out.println(e.getMessage());
}
}
But I'm getting a catch without try error.
Is there any way to use this type of exception handling?
Wrap all the throws inside a single try.
public void myMethod(){
try {
if (whatever){
throw new CardException();
}
if (something else){
throw new InvalidCardException();
}
if (scenario 3){
throw new TwoCardsException();
}
}
catch (CribbageException e) {
System.out.println(e.getMessage());
}
}

Exception Handling; Try Catch

Here's my code:
class FinallyDemo {
static void myMethod(int n) throws Exception{
try {
switch(n) {
case 1:
System.out.println("1st case");
return;
case 3:
System.out.println("3rd case");
throw new RuntimeException("3!");
case 4:
System.out.println("4th case");
throw new Exception("4!");
case 2:
System.out.println("2nd case");
}
catch (RuntimeException e) {
System.out.print("RuntimeException: ");
System.out.println(e.getMessage());
} finally {
System.out.println("try-block entered.");
}
}
public static void main(String args[]){
for (int i=1; i<=4; i++) {
try {
FinallyDemo.myMethod(i);
} catch (Exception e){
System.out.print("Exception caught: ");
System.out.println(e.getMessage());
}
System.out.println();
}
}
}
Now, doesnt it work this way:
If I have a try and catch block in the method itself then I need not write
method_name(int n) throws Exception?
Doesnt try-catch block in the method that throws exception prevents from writing "throws exception" in the method that throws exception?
In your example, the case 4 throws an exception while in the catch you are just catching the RuntimeException. Since there is not catch for Exception, your method needs to declare that it throws Exception.
If you were to add a catch for Exception, you wouldn't need to throw Exception. This will work.
static void myMethod(int n) {
try {
switch (n) {
case 1:
System.out.println("1st case");
return;
case 3:
System.out.println("3rd case");
throw new RuntimeException("3!");
case 4:
System.out.println("4th case");
throw new Exception("4!");
case 2:
System.out.println("2nd case");
}
} catch (RuntimeException e) {
System.out.print("RuntimeException: ");
System.out.println(e.getMessage());
} catch (Exception e) {
System.out.print("Exception: ");
System.out.println(e.getMessage());
}
finally {
System.out.println("try-block entered.");
}
}
You don't need the throws clause if and only if the type of exception being thrown is caught (or if it extends RuntimeException. In your case, you throw an Exception with the statement throw new Exception("4!");, but you only catch the type RuntimeException.
If you add a catch block for Exception, then you will no longer need the throws clause. For example:
static void myMethod(int n) throws Exception{
try {
switch(n) {
case 1:
System.out.println("1st case");
return;
case 3:
System.out.println("3rd case");
throw new RuntimeException("3!");
case 4:
System.out.println("4th case");
throw new Exception("4!");
case 2:
System.out.println("2nd case");
}
} catch (RuntimeException e) {
System.out.print("RuntimeException: ");
System.out.println(e.getMessage());
} catch(Exception e) {
System.out.print("Exception: ");
System.out.println(e.getMessage());
} finally {
System.out.println("try-block entered.");
}
}
Yes, provided you're catching all exception types that can be thrown by the method.
In your code, you throw an Exception but do not supply a catch block for it (you are only catching RuntimeException), therefore you must declare your method as throwing Exception
You would need:
...
catch (RuntimeException e) {
System.out.print("RuntimeException: ");
System.out.println(e.getMessage());
} catch (Exception e) {
System.out.print("Exception: ");
System.out.println(e.getMessage());
} finally {
...
Doesnt try-catch block in the method that throws exception prevents from writing "throws exception" in the method that throws exception?
No, you can always declare to throw exceptions, even if you do not.
Among other things this is useful to allow subclasses to throw them (because they are not allowed to add additional throw clauses). It also allows you to later change the implementation without changing the exception interface.
Right now are tow types of exceptions
Subclasses of Exception.
Subclasess of RuntimeException
The subclasses of Exception are know as checked exception and the compiler ensures that these are managed in try/catch block or through the modifier throws Exception (or subclass) on method.
The subclasess oF RuntimeException are know as unchecked exception and the compile don't require any mechanism for manage it.
Now if you use the modifier throws Exception (or subclass) on a method the compiler will require you manage it with try/catch.
Since you throw both a RuntimeException and an Exception in the switch, you either need to catch both or the method needs to throw the Exception so it can be handled in the method calling myMethod
To catch both use:
catch (RuntimeException e) {
System.out.print("RuntimeException: ");
System.out.println(e.getMessage());
}catch (Exception e) {
System.out.print("Exception: ");
System.out.println(e.getMessage());
}
Make sure the catch of Exception is always last, otherwise it will also catch the RuntimeException since it extends Exception
You are handling the exception in TWO ways. Firstly if you extend the directly call the Exception class as you have done when declaring the method
method_name(int n) throws Exception
What this means is that no matter what type of exception occurs in the method it will always be able to catch it, For example if an Arithmetic Exception or a NullPointerException or an ArrayIndexOutOfBoundsException occurs inside the method your above declaration will be able to catch each and every one of them. Because of that there is no actual purpose of having the try catch block as well placed inside that method because even RunTimeException is part of the Exception Class hierarchy.
Therefore if I understood your question correctly the program will execute and then catch the exception from the catch block, failing which it will catch it from the method declaration.
Hope it answers your query.

Java: Hypothetical question about finally block

What happens if you throw an error in a finally block? Does it get handled in one of the corresponding catch clauses?
Only if you put another try-catch block in the finally block. Otherwise it's an error like any other.
You need to include try-catch blocks inside the finally or catch blocks.
e.g.:
try {
// your code here
} finally {
try {
// if the code in finally can throw another exception, you need to catch it inside it
} catch (Exception e) {
// probably not much to do besides telling why it failed
}
} catch (Exception e) {
try {
// your error handling routine here
} catch (Exception e) {
// probably not much to do besides telling why it failed
}
}
It will not handle exception until it is caught in finally block it self.
public static void main(String[] args) throws Exception {
try {
System.out.println("In try");
} catch (Exception e) {
System.out.println("In catch");
} finally{
throw new Exception();
}
}
Above code will throw exception but if you do as follows it will work:
public static void main(String[] args){
try {
System.out.println("In try");
} catch (Exception e) {
System.out.println("In catch");
} finally{
try{
throw new Exception();
}catch(Exception e){}
}
}
Nope. It would be caught by a catch where then entire try/catch/finally was nested within another try/catch. The exception would otherwise be thrown out of the function, and would be handled by the caller of the function.
No it doesn't. You will have to handle with it IN the finally block or define a proper throw declaration in the method description.
No, a catch block can only catch exceptions thrown within the corresponding try block - not a finally block. (Of course, if that finally block is within another try block, the catch clauses for that try block are still used.)
The relevant section in the JLS is 14.20.2. Each of the flows listed there has something like this:
If the finally block completes abruptly for any reason, then the try statement completes abruptly for the same reason.
In other words, there's no attempt for any catch clauses associated with the finally block to handle the exception.
The order of execution is normally directly indicated by the order of statements: 1. try, 2. catch exceptions in the specified order (only one catch is executed), 3. finally.
So when the finally block is executed (note that this is always the case, even in the case of a return statement or exception being thrown in the try or catch blocks) the execution of try statement is in its last phase and thus it cannot catch further throwables. As already pointed out, the exception has to be handled in a location further down the stack (or up, depends on the view point ;) ).

Categories

Resources