try-catch

img src: bing image

First, something to think about... :

Second, a few things to keep in mind... :

In this blog, I will focus on these topics:


try-carch

img src: bing image

Now, let's dive right in... :

1. When do codes after finally in Java execute?

See codes below:


        public class TestFinally {
            public static void main(String[] args){
                try{
                    return;
                }
                finally{
                    System.out.println("Finally");
                }
            }
        }
        

Program Output:


            Finally
        

conclusion1: No exception occured, finally still gets executed.

If we replace return to a normal output code:


        public class TestFinally {
            public static void main(String[] args){
                try{
                    int a=3;
                    a+=5;
                    System.out.println(a);
                }
                finally{
                    System.out.println("Finally");
                }
                int b=5;
                b+=5;
                System.out.println(b);
            }
        }
        

Program Output:


            8
            Finally
            10
        

conclusion2: Codes after finally will be executed.

Adding return in try won't be compiled because compiler found out this part of codes:


        int b=5;
        b+=5;
        System.out.println(b); 
        

are unreachable code.

Some extra examples, example set 1:


        public class TestFinally {
            public static void a() throws Exception{
                try{
                    throw new Exception();
                }
                catch(Exception e){
                    System.out.println("exception000");
                }
                finally{
                    System.out.println("finally111");
                }
            }
            public static void main(String[] args){
                try{
                    a();
                }
                catch(Exception e){
                    System.out.println("exception");
                }
                System.out.println("finished");
            }
        } 
        

Program Output:


            exception000
            finally111
            finished
        

Exception was caught in a(), catch in main will not be executed. Codes after catch will be executed.

If we commented catch in a():


        public class TestFinally {
            public static void a() throws Exception{
                try{
                    throw new Exception();
                }
                /*catch(Exception e){
                    System.out.println("exception000");
                }*/
                finally{
                    System.out.println("finally111");
                }
            }
            public static void main(String[] args){
                try{
                    a();
                }
                catch(Exception e){
                    System.out.println("exception");
                }
                System.out.println("finished");
            }
        }
        

Program Output:


            finally111
            exception
            finished
        

Exception did not get caught in a(), but was caught at catch in main. Codes after catch will be executed.

If we commented finally in a() instead:

try-catch

img src: bing image

        package trycatchfinally;

        public class TestFinally {
            public static void a() throws Exception{
                try{
                    throw new Exception();
                }
                catch(Exception e){
                    System.out.println("exception000");
                }
                /*finally{
                    System.out.println("finally111");
                }*/
            }
            public static void main(String[] args){
                try{
                    a();
                }
                catch(Exception e){
                    System.out.println("exception");
                }
                System.out.println("finished");
            }
        }
        

Program Output:


            exception000
            finished
        

Exception was caught in a(), codes after catch in main will be executed.

example set 2:


        public class TestFinally {
            public static String output="";
            public static void a(int i){
                try{
                    if(i==1){
                        throw new Exception();
                    }
                    output+="1";
                }
                catch(Exception e){
                    output+="2";
                    return;
                }
                finally{output+="3";}
                output+="4";
            }
            public static void main(String[] args){
                a(0);
                a(1);
                System.out.println(TestFinally.output);
            }
        } 
        

Program Output:


            13423
        

If we remove return phrase... :


        package trycatchfinally;

        public class TestFinally {
            public static String output="";
            public static void a(int i){
                try{
                    if(i==1){
                        throw new Exception();
                    }
                    output+="1";
                }
                catch(Exception e){
                    output+="2";
                    //return;
                }
                finally{output+="3";}
                output+="4";
            }
            public static void main(String[] args){
                a(0);
                a(1);
                System.out.println(TestFinally.output);
            }
        }
        

Program Output:


            1234234
        

conclusion3: If there is return in try, codes after finally will not be executed. Same thing goes for catch.

2. When does finally in Java codes be executed? Or doesn't be executed?

Now that we know codes after finally get executed or not depend on whether there is retuen in try or catch, it's time to think deeper...

3. finally is executed before or after return ?

One statement I agree on:

finally in Java codes is executed after return, but before return returns value.

See codes below:


        public class TestFinally {
            public static void main(String[] args) {        
                System.out.println(test1());
            }
            public static int test1() {
                int b = 20;
                try {
                    System.out.println("try");
                    return b += 80; 
                }
                catch (Exception e) {
                    System.out.println("catch");
                }
                finally {           
                    System.out.println("finally");          
                    if (b > 25) {
                        System.out.println("b>25, b = " + b);
                    }
                }       
                return b;
            }  
        }
        

Program Output:


            try
            finally
            b>25, b = 100
            100
        

return is executed first, but before return returns value, finally is executed. Then return returns value.


        public class TestFinally {
            public static void main(String[] args) {	        
                System.out.println(test11());
            }	    
            public static String test11() {
                try {
                    System.out.println("try");
                    return test12();
                } finally {
                    System.out.println("finally");
                }
            }
            public static String test12() {
                System.out.println("return statement");
                return "after return";
            }
        }
        

Program Output:


            try
            return statement
            finally
            after return
        

4. If there is also return in finally, then should it just return? Will retuen in try return?

See codes below:


        public class TestFinally {
            public static void main(String[] args) {
                System.out.println(test2());
            }
            public static int test2() {
                int b = 20;
                try {
                    System.out.println("try");
                    return b += 80;
                } catch (Exception e) {
                    System.out.println("catch");
                } finally {
                    System.out.println("finally");
                    if (b > 25) {
                        System.out.println("b>25, b = " + b);
                    }
                    return 200;
                }
                // return b;
            }
        }
        

Program Output:


            try
            finally
            b>25, b = 100
            200
        

conclusion: return in finally will return, regardless of return in try. Meaning it will override return in try.
Also, once there is return in finally, return b; outside becomes unreachable. It will need to be commented out.is executed. Then return returns value.

5. If there is no return in finally but in try, then how will retuen in try return?


        try{
            return {expression A};
        }finally{
            do some work;
        }
        

We now know that finally block generally gets executed. But in what order?
  1. execute {expression A}, push result into top of operand stack. (Some say copy to top of operand stack.)
  2. copy the top of operand stack (result of {expression A}) to local variable table.
  3. execute finally.
  4. push value in local variable table in step 2 back to operand stack. (Some say copy it to top of operand stack, not exactly push.)
  5. return value at the top of operand stack.
conclusion: After step 1, value to return is already set. In order to execute finally, JVM will temporarily move the return value to local variable table, to free up operand stack for finally. And when finally is complete, JVM will return the value to top of operand stack. So no matter what finally do (except returning a static value like return 200;), value to return will not be affected. finally is designed for clean up, not alter return value.

6. If finally do not have return in it but altered the variable to return. Then how will retuen in try return? Altered or unaltered?

See codes below:


        public class TestFinally {
            public static void main(String[] args) {
                System.out.println(test3());
            }
            public static int test3() {
                int b = 20;
                try {
                    System.out.println("try");	            
                    return b += 80;
                } catch (Exception e) {
                    System.out.println("catch");
                } finally {
                    System.out.println("finally");
                    if (b > 25) {
                        System.out.println("b>25, b = " + b);
                    }
                    b = 150;
                }
                return 2000;
            }
        }
        

Program Output:


            try
            finally
            b>25, b = 100
            100
        
conclusion: return did not changed to 150, so if finally try to alter a basic data types variables like an int or double, affects would not take place. But if it tries to alter a wrapper class like Interger, or some normal object like Map map = new HashMap();, affects would take place.

reference:

[1] https://stackoverflow.com/questions/65035/does-finally-always-execute-in-java