JAVA final in-depth understanding

The Java keyword final usually means that the data modified by it cannot be changed. There may be two reasons for not wanting to change: design or efficiency. Main features:

  • Use of final data
  • Use of final parameters
  • use of final method
  • final classes cannot be inherited

final data

1.1 final modified variable

Once a final variable is initialized, its value cannot be changed

The value here for an object or array refers to the reference address of the object or array. Therefore, after a thread defines a final variable, any other thread gets the variable. But one thing to note is that when the final variable is an object or an array, although we cannot say that this variable is assigned to other objects or arrays, we can change the field of the object or the elements in the array.

Changes to fields or data elements of this object variable by a thread do not have thread visibility;

So final modified variables must be initialized

public static final String LOAN = "loan";
LOAN = new String("loan") //invalid compilation error

Final variable initialization timing:

  • Initialize at definition
  • In the initialization block, but not in the static initialization block, static final instance variables can only be in the static initialization block
  • In the constructor, but static final instance variables cannot be in it

characteristic

  • Modified variables are basic data types: tell the compiler that this piece of data is immutable, which can reduce some runtime burdens when performing calculations;
  • final variables must be initialized when they are declared;
  • final instance variables must be initialized at the end of all constructors;
  • In JMM, the initialization action of the final field must be completed before the return of the constructor;
package com.quancheng;

import java.util.Random;

public class FinalTest {
    private static Random random = new Random(20);
    private final int VALUE_A = 10;
    private static final int VALUE_B = 20;
    public static final int VALUE_C = random.nextInt(10);
    public  final int VALUE_D = random.nextInt(10);
    public static void main(String[] args) {
        FinalTest test = new FinalTest();
        //test.VALUE_A = 5;//Error:不可以这样做
        //test.VALUE_B  =21;//Error:不可以这样做

        FinalTest finalT = new FinalTest();
        FinalTest finalT1 = new FinalTest();

        System.out.println("VALUE_C:"+VALUE_C);
        System.out.println("VALUE_C:"+finalT.VALUE_C);
        System.out.println("VALUE_C:"+finalT1.VALUE_C);
        System.out.println("---------");
        System.out.println("VALUE_D:"+finalT.VALUE_D);
        System.out.println("VALUE_D:"+finalT1.VALUE_D);
    }
}

output==>
VALUE_C:3
VALUE_C:3
VALUE_C:3
---------
VALUE_D:1
VALUE_D:1

The above results lead to the point that we cannot assume that the value of a data can be known at compile time just because it is final. This is illustrated using randomly generated VALUE_C and VALUE_D at runtime. The sample code shows the difference between final values ​​defined as static and non-static. This difference is only apparent when the values ​​are initialized at runtime, because the compiler treats compile-time values ​​the same (and they may disappear due to optimization). The value using static final cannot be changed by a new object. This is because it is already initialized at load time, not every time a new object is created.

1.2 final is used for reference

When final is used for a reference to an object instead of a primitive type, final makes the value invariant for primitive types, and final makes the reference immutable for object references. Once a reference is initialized to point to an object, it cannot be changed to point to another object. However, the data of the object itself can be modified

package com.game.lll;

public class FinalTest {  
    private final int a = 10;  

    private final Value v1 = new Value(10);  

    public static void main(String[] args) {  
        FinalTest test = new FinalTest();  
        //test.a = 5;//不可以这样做  
        test.v1.value++;  
        //test.v1 = new Value(12);//Error:不可以这样做  
        System.out.println("对象内的数据:"+test.v1.value);  
    }  

    class Value{  
        int value;   
        public Value(int value) {  
            this.value = value;  
        }  
    }  
}

1.3 final for arrays

Final is the same as when it is used for arrays and references. The array is just another kind of reference. The reference to this variable cannot be reassigned, but the object itself can be modified. code show as below:

package com.game.lll;    

public class FinalTest {    
    private final Value v1 = new Value(10);    

    private final int[] values = { 1, 2, 3, 4, 5, 6 };    

    public static void main(String[] args) {    
        FinalTest test = new FinalTest();    
        //test.a = 5;//不可以这样做    
        test.v1.value++;    
        //test.v1 = new Value(12);//Error:不可以这样做  
        test.values[0] = 100;//对象本身是可以修改的    
        for(int i = 0; i < test.values.length;i++){    
            System.out.println(test.values[i]++);//对于这个变量的引用是不能被重新赋值    
        }    
    }    

    class Value{    
        int value;     
        public Value(int value) {    
            this.value = value;    
        }    
    }    
}

1.4 Blank final

Java allows the generation of "blank finals", which are fields that are declared final but given an undefined initial value. code show as below:

package com.game.lll;  

public class BlankFinal {  
    private final int a;  

    public BlankFinal(int i)  
    {  
        this.a = i;  
    }  


    public static void main(String[] args) {  
        BlankFinal blankFinal = new BlankFinal(5);  
        System.out.println(blankFinal.a);  
    }  
}

Although a is not directly assigned a value, a is initialized in the constructor. So in any case, make sure final is initialized before use

In JMM, the initialization action of the final field must be completed before the constructor return

final method

The reason for using a final method is to lock the method in case any inheriting class modifies its meaning. A method declared final cannot be overridden;

  • When calling a final method, insert the method body directly into the calling place instead of making a method call, which can improve program efficiency (inline mechanism)
  • If you think a method is functional enough that it doesn't need to be changed in subclasses, you can declare the method final
  • Final methods are faster than non-final methods because they are statically bound at compile time and do not need to be dynamically bound at runtime
class PersonalLoan{
    public final String getName(){
        return "personal loan";
    }
}

class CheapPersonalLoan extends PersonalLoan{
    @Override
    public final String getName(){
        return "cheap personal loan"; //compilation error: overridden method is final
    }
}

final class

When you define a class as final class, then subclasses cannot inherit the class

Consider an interesting phenomenon:

byte b1=1;
byte b2=3;
byte b3=b1+b2;  //当程序执行到这一行的时候会出错,因为b1、b2可以自动转换成int类型的变量,运算时java虚拟机对它进行了转换,结果导致把一个int赋值给byte
final byte b1=1;
final byte b2=3;
byte b3=b1+b2;  //不会出错,相信你看了上面的解释就知道原因了。

Other features

  • Once a final variable is initialized, its value cannot be changed;
  • final variables should apply all uppercase (coding rules);
  • All methods of final classes are implicit final methods;
  • A class cannot be declared final and abstract at the same time;

Knowledge point

  • Why out/err in System class can change value

    public final static InputStream in = null;
    public final static PrintStream out = null;
    public final static PrintStream err = null;

    setOut/setIn/setErr are native methods that can bypass the access control mechanism of the java language; this rare situation comes from early JAVA and will not be encountered elsewhere;

    private static native void setIn0(InputStream in);
    private static native void setOut0(PrintStream out);
    private static native void setErr0(PrintStream err);

Guess you like

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