Thorough interview 3: Deep understanding of final, finally and finalize

One, final

final bronze

Final can modify classes, methods, and variables.

  • When modifying a class, it means that this class cannot be inherited.
  • When modifying a method, it means that this method cannot be overridden.
  • It must be initialized when modifying the variable. It can be initialized in the constructor when the code is fast when it is defined. Once initialized, it is not allowed to be modified.

final king

1. Why is it mandatory to add final to anonymous internal classes to access local variables?

We look at the following code:

public class Test {
    
    
    public static void main(String[] args) {
    
    
        int a = 8;
        new Thread(new Runnable() {
    
    
            @Override
            public void run() {
    
    
                System.out.println(a);
            }
        }).start();
    }
}

Before jdk1.8, this code failed to compile because the a variable did not add final. But after jdk is 1.8, you are no longer forced to add final, but the compiler will automatically add final to you.

Why does java syntax require us to use final modification?

Let's decompile, the decompiled code of the inner class Test$1.class

final class Test$1 implements Runnable {
    
    
    Test$1(int var1) {
    
    
        this.val$a = var1;
    }

    public void run() {
    
    
        System.out.println(this.val$a);
    }
}

The decompiled code is somewhat omitted, and the definition of the val$a variable is missing. This is not the point, it doesn't matter.

As can be seen from the above decompiled code, the reason why the anonymous inner class can access the local variable is because the value of this local variable is passed into the anonymous inner class at the bottom layer, and it exists as a member variable of the anonymous inner class. This value The transfer process is completed by the constructor of the anonymous inner class.

Because after the data is copied, if the final modification is not used, the original local variables can be changed. If the local variable changes, the anonymous inner class does not know (because it just copies the value of the local invariant, not the local variable used directly). Here is a chestnut: the original local variable points to object A, after the anonymous inner class is created, the member variables in the anonymous inner class also point to the A object. But after a while, the value of the local variable points to another B object, but at this time the anonymous inner class still points to the original A object. Then the program continues to run, which may cause the program to run differently than expected.

2. What performance optimizations has the JVM made for local variables declared as final?

This question is more complicated, R University has already done a more detailed analysis on this, you can take a look if you are interested.

[https://www.zhihu.com/question/21762917]:

The conclusion is: on the premise that it can be compiled, no matter whether the local variable is declared with or without the final keyword modification, the efficiency of its access is the same.

Two, finally

finally It is a mechanism to ensure that the program must be executed. It is also a keyword in Java. Generally speaking, finally is generally not used alone. It is generally used with try...finally block or try...catch...finally.

  • The finally block is only executed when the try block is executed, and finally does not exist alone.
  • The finally block is executed before the control transfer statement when it leaves the try block after the execution is completed or the try block is not completed but is followed by a control transfer statement (return/continue/break).
public class Test {
    
    
    public static void main(String[] args) {
    
    
        System.out.println(getNum());
    }
    public static int getNum() {
    
    
        int a = 0;
        try {
    
    
            a = 1;
            return a;
        } finally {
    
    
            ++a;
            System.out.println("finally执行");
        }
    }
}

Run output:

finally执行
1
  • If there is an exception belonging to exception and its subclasses in the try statement block, jump to catch processing
  • If an exception that does not belong to exception and its subclasses occurs in the try statement block, jump to finally processing
  • If a new exception occurs in the catch statement block, jump to finally processing
  • If there is a return statement in try...catch, then the return value is temporarily stored, and after the finally is executed, the return value or the returned temporary value will be executed.

Three, finalize

Java technology allows the use of the finalize() method to do the necessary cleanup before the garbage collector clears the object from memory. This method is called by the garbage collector when it determines that the object is not referenced. It is defined in the Object class, so all classes inherit it. Subclasses override the finalize() method to organize system resources or perform other cleanup tasks.

finalize works like this: Once the garbage collector is ready to release the memory occupied by objects, it will first call the finalizemethod, and the next time garbage collection action occurs, will really recovered memory occupied by the object. Garbage collection is only related to memory.

We know that, Java and C ++ is a significant difference is that Java can 自动管理内存, in Java, because the automatic recovery mechanism GC, and therefore does not guarantee that finalizethe method will be timely implementation of the (recovery time to junk the object of which is uncertain), there is no guarantee They will be executed.

In other words, the execution period of finalize is uncertain, and we cannot rely on the finalize method to help us carry out garbage collection. It may happen that gc is not triggered before we run out of resources, so it is recommended to display when resources are used up The release method, such as the close method. In addition, the finalize method will also cause exceptions.

So we do not advocate the use of finalize method in daily development

Guess you like

Origin blog.csdn.net/u013277209/article/details/109450934