Java try catch finally return execution

public static  int testBasic(){
        int i = 1;
        try{
            i++;
            System.out.println("try block, i = "+i);
        }catch(Exception e){
            i ++;
            System.out.println("catch block i = "+i);
        }finally{
            i = 10;
            System.out.println("finally block i = "+i);
        }
        return i;
}

 

That's right, it will be executed in order. The code segment in the try will be executed first. If there is no exception, it will enter the finally, and finally return. Then the output is as follows:

 

try block, i = 2
finally block i = 10
main test i = 10

 

This is no problem, what if we put the return statement into try catch

 

public static  int testBasic(){
        int i = 1;
        try{
            i++;
            System.out.println("try block, i = "+i);
            return i;
        }catch(Exception e){
            i ++;
            System.out.println("catch block i = "+i);
            return i;
        }finally{
            i = 10;
            System.out.println("finally block i = "+i);
        }
}

 

The output is:

 

try block, i = 2
finally block i = 10
main test i = 2

 

The code is executed sequentially from try to finally. Since finally is executed anyway, the statements in try will not return directly. In the return block of the try statement, the reference variable returned by return is not the reference variable i defined outside the try statement, but the system redefines a local reference i', which points to the value corresponding to reference i, which is 2. Even if the reference i points to the value 10 in the finally statement, because the reference returned by return is not i, but i', the value of the reference i has nothing to do with the return value in the try statement.

 

However, this is only part of it. If you replace i with a wrapper type instead of a primitive type, let's see what the output will look like. Here is an example:

 

public static  List<Object> testWrap(){
        List<Object> list = new ArrayList<>();
        try{
            list.add("try");
            System.out.println("try block");
            return list;
        }catch(Exception e){
            list.add("catch");
            System.out.println("catch block");
            return list;
        }finally{
            list.add("finally");
            System.out.println("finally block ");
        }
}

 

The print result is as follows:

try block
finally block 
main test i = [try, finally]

 

It can be seen that the operation on the list collection in finally takes effect, why is this? We know that primitive types are stored on the stack, and for non-primitive types are stored in the heap, and the address in the heap is returned, so the content is changed.

 

Ok, now let's add a return to finally to see where the statement returns from.

 

public static  int testBasic(){
        int i = 1;
        try{
            i++;
            System.out.println("try block, i = "+i);
            return i;
        }catch(Exception e){
            i ++;
            System.out.println("catch block i = "+i);
            return i;
        }finally{
            i = 10;
            System.out.println("finally block i = "+i);
            return i;
        }
}

 

The output is as follows:

try block, i = 2
finally block i = 10
main test i = 10

As you can see, it is returned from the finally block. It can be seen that the JVM ignores the return statement in try. But the IDE will have a yellow warning prompt for the return added in finally. This is why, adding a line of code to the try will execute an exception, as follows:

 

public static  int testBasic(){
        int i = 1;
        try{
            i++;
            int m = i / 0 ;
            System.out.println("try block, i = "+i);
            return i;
        }catch(Exception e){
            i ++;
            System.out.println("catch block i = "+i);
            return i;
        }finally{
            i = 10;
            System.out.println("finally block i = "+i);
            return i;
        }
}

 

The print result is as follows:

catch block i = 3
finally block i = 10
main test i = 10

It can be seen that because there is a return statement in finally, the exceptions in try and catch are digested and the occurrence of exceptions is blocked, which is contrary to the original intention of using try and catch in the early stage, so the compiler will also prompt a warning.

So if there is an exception in finally, what will be the impact on the exception in try and catch?

 

public static  int testBasic(){
        int i = 1;
        try{
            i++;
            Integer.parseInt(null);
            System.out.println("try block, i = "+i);
            return i;
        }catch(Exception e){
            String.valueOf(null);
            System.out.println("catch block i = "+i);
            return i;
        }finally{
            i = 10;
            int m = i / 0;
            System.out.println("finally block i = "+i);
        }
}

 

Here we forcibly add exception statements to try and catch, and the print results are as follows:

Exception in thread "main" java.lang.ArithmeticException: / by zero
at tryandcatch.TryAndCatch.testBasic(TryAndCatch.java:25)
at tryandcatch.TryAndCatch.main(TryAndCatch.java:45)

This prompt represents the exception information in finally, that is to say, once an exception occurs in finally, the exception information in try and catch will be digested, and the purpose of exception information processing will not be achieved.

 

To summarize the above test:

1. The finally statement will always execute

2. If there is a return statement in try and catch, but there is no return in finally, then modifying data in finally except for the packaging type, static variables, and global variables will not have any effect on the variables returned in try and catch ( packaging ). types, static variables change, global variables )

3. Try not to use the return statement in finally. If it is used, the return statement in try and catch will be ignored, and the exception in try and catch will also be ignored, which shields the occurrence of errors.

4. Avoid re-throwing exceptions in finally. Once an exception occurs in finally, the code execution will throw the exception information in finally, and the exceptions in try and catch will be ignored.

 

Therefore, in practical projects, finally is often used to close streams or database resources, and does not do other operations.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325138902&siteId=291194637