28

I have a program as following:

public class Main {
    public static void main(String[] args)throws Exception
    {
        int res = test();
        System.out.println("after call , res = " + res) ;
    }

    public static int test()throws Exception
    {
        try
        {
            return 10/0;
        }
        finally
        {
            System.out.println("finally") ;
        }
    }
}

after run above program , following result saw in console:

finally
Exception in thread "main" java.lang.ArithmeticException: / by zero
    at Main.test(Main.java:17)
    at Main.main(Main.java:7)

this behavior is normal because exception thrown to main method.

Then I change code as following :

public class Main {
    public static void main(String[] args)throws Exception
    {
        int res = test();
        System.out.println("after call , res = " + res) ;
    }

    public static int test()throws Exception
    {
        try
        {
            return 10/0;
        }
        finally
        {
            System.out.println("finally") ;
            return 20;
        }
    }
} 

When run above program I saw following result in console:

finally
after call , res = 20

My question related to second format. Why when return in finally block , exception not thrown to main method?

Sam
  • 6,770
  • 7
  • 50
  • 91

11 Answers11

13

When your exception is thrown, it will first go through your finally block.

If your finally block does not return or throw anything then the original exception is passed on.

If your finally block on the other hand returns a value, then the exception is no longer propagated at all.

bvdb
  • 22,839
  • 10
  • 110
  • 123
8

Look at the execution of try catch finally.

From java language specification -jls-14.20.2

If the run-time type of V is not assignment compatible with a catchable exception class of any catch clause of the try statement, then the finally block is executed. Then there is a choice:

If the finally block completes normally, then the try statement completes abruptly because of a throw of the value V.

If the finally block completes abruptly for reason S, then the try statement completes abruptly for reason S (and the throw of value V is discarded and forgotten).

Community
  • 1
  • 1
Suresh Atta
  • 120,458
  • 37
  • 198
  • 307
  • 1
    Just wondering, what is reason S ? – bvdb Oct 13 '15 at 09:37
  • 1
    @bvdb In this case, the exception. – Suresh Atta Oct 13 '15 at 09:42
  • 1
    @bvdb JLS 14.1: https://docs.oracle.com/javase/specs/jls/se8/html/jls-14.html; Sloppy said: It can be any statement which stops the block from ending at its ending parenthesis: A `break`, `continue`, `return` or an exception. – flo Oct 13 '15 at 09:45
7

From the JLS (emphasis mine):

If execution of the try block completes abruptly because of a throw of a value V, then there is a choice:
[...]
If the run-time type of V is not assignment compatible with a catchable exception class of any catch clause of the try statement, then the finally block is executed. Then there is a choice:

  • If the finally block completes normally, then the try statement completes abruptly because of a throw of the value V.

  • If the finally block completes abruptly for reason S, then the try statement completes abruptly for reason S (and the throw of value V is discarded and forgotten).

This means if you return within the finally block, the method returns without throwing an exception.

Besides return, there are other statementes that can cause the finally block to complete abruptly and forget about the exception. They are defined in the JLS Section 14.1. Basically, it is break, continue, return or an exception (either thrown or caused by a statement/method). The complete try/catch/finally block then completes with this reason.

There are a few more cases ín the specification of try/catch/finally, especially if there is no exception or a matching catch clause exists. It comes down to finally beats catch beats try.

Scorpion
  • 3,938
  • 24
  • 37
flo
  • 9,713
  • 6
  • 25
  • 41
3
  1. If you use return in the finally section, you lose exception. Method will be finished with a normal type of a return value.
  2. If you don't use return in the finally section, in your case, method will be finished with exception.

The first case:

try {
    throw new Exception();
} finally {
    //Exception will be lost, normal shutdown of the method
    return;
}

The second case:

try {
    throw new Exception();
} finally {
    //Exception won't be lost, we'll get Exception in the main method
}

The third case:

try {
    throw new Exception();
} finally {
    throw new IOException();
    // we lost Exception, IOException will be thrown
}

Note: Using the finally section to throw exceptions or to return values is a bad practice. This section has been created, for example, for closing external resources.

Andrew Tobilko
  • 48,120
  • 14
  • 91
  • 142
2

Everything in a finally block is executed before the exception is thrown, so if you return in a finally block, the exception will not be thrown at all. It's generally a bad idea to return from the finally block for this reason.

Take a look at this blog for some info about this.

Ben Green
  • 3,953
  • 3
  • 29
  • 49
0

Java's return doesn't always return, this might entertain.

Ken
  • 30,811
  • 34
  • 116
  • 155
0

The return statementin the finally block was basically stopping the exception that happened in the try block from propagating up even though it wasn't caught.

But Java compiler do notify warnings when writing this piece of code. Though return statements should always lie in try block, and finally block is uasully for releasing/closing connections, pointers etc.

It seems the way Java behaves.

Have a look here

Community
  • 1
  • 1
Ankur Singhal
  • 26,012
  • 16
  • 82
  • 116
0

If you read java doc of finally then it says,

it allows the programmer to avoid having cleanup code accidentally bypassed by a return, continue, or break. Putting cleanup code in a finally block is always a good practice, even when no exceptions are anticipated.

So if you put clean-up code after the finally block, it won't get called if there is an exception.

0

In the first case, finally block is executed as its behavior but it didn't caught the exception but the exception is thrown via main method. Check it via this example

public class HelloWorld{

     public static void main(String []args)throws Exception
     {
        try
        {
        int res = test();
        System.out.println("after call , res = " + res) ;
        }
        catch(Exception ex)
        {
            System.out.println("Main Catch") ;
        }
     }
     public static int test()throws Exception
     {
        try
        {
            return 10/0;
        }
        finally
        {
            System.out.println("finally") ;
        }
    }
}

In the above code, Main Catch got executed.

In the second case, you returned the number, so there was no exception in the main method.

Harshit
  • 5,147
  • 9
  • 46
  • 93
0

Because finally block is always executed , whether exception occur or not, and if you return from finally means , you are sending your execution to the calling method and you lose the Exception. So it generates warning as well.

enter image description here

Community
  • 1
  • 1
Sindhoo Oad
  • 1,194
  • 2
  • 13
  • 29
0

In first program when ArithmeticException occur in try block then call the finally block and after execute the finally block , exception occur . because exception is not handled by program . Second Program when finally block execute after that return statement execute and no exception occur because after the return statement execute compiler return in main method and remaining execution will not execute in finally block . So exception will not occur .