final keyword
Basic usage: modify classes, methods and variables
1. When decorating a class: it indicates that the class cannot be inherited, and the member variable in the final class is implicitly specified as final
2. When decorating a method: lock the method to prevent the inherited class from modifying its definition (prevent overwriting) (in addition, for efficiency, in the early java version, the final method was converted to an embedded call, which can be checked if you are interested, but it is basically unavailable now)
Supplement: * * the private method in the class will be implicitly specified as final
3. Modification variables
Declare a constant
For the final variable, if it is a basic data type, its value cannot be changed after initialization. If it is a reference type, it cannot point to other objects after initialization
**For final and static
The two have different effects on variables. The main difference is that final ensures that variables are immutable, and static means that only one copy of variables is saved
Deep understanding of final
1. Compile time constants and runtime constants
Constants declared by final are divided into compile time constants and runtime constants
Compile time constant: if the final variable is a basic type or String type at compile time, and the jvm can determine its exact value, the compiler will use it as a compile time constant, replace it with literal and store it in the class constant pool. When it is needed, it will directly access this constant
private final String q="b";
Runtime constant: refers to the process of reference or acquisition (which can be the acquisition of local variables or the results of some processing processes) without directly assigning a literal value to the final constant, for example:
final int len = "sjt".length();
For runtime constants, during the compilation period, the program does not pay attention to its own value, but only knows its type, and its value is determined at the run stage. During the compilation period, the compilation period constants are directly replaced with literal quantities and written into the class constant pool
2. Dependency on classes
If compile time constants / runtime constants are called at the program entry respectively, then:
Compilation time constants are stored in the class constant pool during compilation, which does not cause class initialization, that is, they do not depend on classes
The runtime constant depends on the class, which will cause the initialization of the class (the class executes immediately)
As mentioned earlier, compile time constants are determined at compile time, while runtime constants are determined at run time, which is why compile time constants do not depend on classes, while runtime constants depend on classes
The following examples (1) and (2) are the cases where calling runtime constants of basic data types and reference data types causes class initialization respectively
//Example (1) class Test { //Static code block static { System.out.println("Class Test Was Loaded!"); } //compile-time constant public static final int num = 10; //Runtime constant public static final int len = "Rhien".length(); } public class Main { public static void main(String[] args) throws Exception { System.out.println("num:"+Test.num); System.out.println("=== after get num ==="); System.out.println("len:"+Test.len); } } /* Printout: * num:10 * === after get num === * Class Test Was Loaded! * len:5 */ //Example (2) class Test1 { public int len_test=0; //Static code block static { System.out.println("Class Test Was Loaded!"); } //compile-time constant public static final int num = 10; //Runtime constant public static final Test1 len =new Test1(); } public class Test { public static void main(String[] args) throws Exception { System.out.println("num:"+Test1.num); System.out.println("=== after get num ==="); System.out.println("len:"+Test1.len.len_test); } } /*Printout *num:10 *=== after get num === *Class Test Was Loaded! *len:0 **/
As can be seen from the above code, num is a compile time constant, and calling it will not cause class initialization, while calling the runtime constant len, whether len is a basic data type or a reference data type, will cause class initialization.
3. Discussion on "compile time constants can be used directly"
Look at an example
public class Test { public static void main(String[] args) { String a = "hello2"; final String b = "hello"; String d = "hello"; String c = b + 2; String e = d + 2; System.out.println((a == c)); System.out.println((a == e)); } } The operation result is: true false
For b, it has been replaced by the literal "hello" at the compilation time, and its value is stored in the class constant pool. For the equation of c, both the left and right sides of "+" are string constants at the compilation time, and the jvm directly connects them at the compilation time and determines the value of c to be stored in the constant pool; For e, if there are variables on both sides of "+", for java, a new StringBuilder will be used for splicing (refer to the specific details). At this time, new is used, and the value of E is placed in the heap. Of course, the addresses of a and E are different, so flash.
4. After the reference variable is modified by final, although it can no longer point to other objects, the content of the object it points to is variable.
5.final and static
static acts on member variables to indicate that only one copy is saved, while final is used to ensure that variables are immutable.
See this blog for the analysis of 4 and 5