Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

try/finally without catch and return value [duplicate]

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?

like image 385
Sam Avatar asked Oct 13 '15 09:10

Sam


People also ask

Is it possible to have a try without catch and finally?

Yes, It is possible to have a try block without a catch block by using a final block. As we know, a final block will always execute even there is an exception occurred in a try block, except System. exit() it will execute always.

What happens if you exclude catch and use only try and finally?

If any of the code in the try block can throw a checked exception, it has to appear in the throws clause of the method signature. If an unchecked exception is thrown, it's bubbled out of the method. The finally block is always executed, whether an exception is thrown or not.

How do you use finally without try catch?

If an exception is thrown prior to the try block, the finally code will not execute. The finally block always executes when the try block exits. So you can use finally without catch but you must use try.

What will happen when try and finally block both return value?

When try and finally block both return value, method will ultimately return value returned by finally block irrespective of value returned by try block.


4 Answers

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.

  • Reference: JLS about try-finally
like image 127
bvdb Avatar answered Oct 16 '22 13:10

bvdb


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).

like image 35
Suresh Atta Avatar answered Oct 16 '22 14:10

Suresh Atta


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.

like image 7
flo Avatar answered Oct 16 '22 13:10

flo


  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.

like image 3
Andrew Tobilko Avatar answered Oct 16 '22 13:10

Andrew Tobilko