A brief analysis of the understanding of Java keywords final and static

  • 2020-06-23 00:25:22
  • OfStack

1. final

Depending on the program context, the Java keyword final has the meaning "this is immutable" or "end-state" and can modify non-abstract classes, non-abstract class member methods, and variables. You may need to block change for two reasons: design or efficiency.

The final class cannot be inherited, there are no subclasses, and the methods in the final class are final by default. final methods cannot be overridden by subclass methods, but can be inherited. The final member variable, which represents a constant, can only be assigned once and does not change after assignment. final cannot be used to modify constructors.

Note: Superclass private member methods cannot be overridden by subclass methods, so methods of type private default to type final.

In general, final is used to declare properties, methods, and classes, representing properties that are immutable, methods that cannot be overridden, and classes that cannot be inherited.

1) final decorates the class

When a class is decorated with final, it indicates that the class cannot be inherited, so there is no chance that the member methods of final class will be overridden and default to final. That means that the class is a leaf class in the inheritance tree, and that the design of the class is considered perfect and does not require modification or extension. A member of the final class can be defined as final or not final. The method, of course, is final. Choose carefully when using final to decorate a class, and avoid designing a class as final for security reasons unless the class will not be used for inheritance in the future.

2) final modification method

There are two reasons to use the final approach. The first is that the method is known to provide the required functionality, does not need to be extended, and is not allowed to be overridden by any subclass that inherits from this class, but can still use the method directly. The second is efficiency. When the compiler calls final methods, it will convert all calls to inline, which greatly improves the execution efficiency. However, when the method body is very large, or when the method is called in multiple places, the calling code expands rapidly and can be inefficient, so use final with caution. Set the method to final only if you want to explicitly prohibit the method from being overridden in a subclass. Such as:


class Test1 { 
 public void f1() { 
  System.out.println("f1"); 
 } 
 // Methods that cannot be overridden by subclasses  
 public final void f2() { 
  System.out.println("f2"); 
 } 
 public void f3() { 
  System.out.println("f3"); 
 } 
 private void f4() { 
  System.out.println("f4"); 
 } 
} 
public class Test2 extends Test1 {  
 public void f1(){  
  System.out.println("Test1 The parent class method f1 Be overwritten !"); 
 } 
 public static void main(String[] args) { 
  Test2 t = new Test2(); 
  t.f1();  
  t.f2(); // The call is inherited from the parent class final methods  
  t.f3(); // Calls methods inherited from the parent class  
  //t.f4(); // The call failed and could not be inherited from the parent class  
 } 
} 

Note: The private method of the class is implicitly specified as the final method.

3) final modifies the variable

The modifier variable is the most frequently used variable of final. For a variable of final, if it is a variable of basic data type, its value 1 cannot be changed once it is initialized. If it is a variable of reference type, it cannot point to another object after it has been initialized. The final variable can be initialized in two places, 1 where it is defined and 2 where it is in the constructor, and only 1 is selected. final modifies three types of variables: static variables, instance variables, and local variables, representing three types of constants, respectively. final variable definitions, can first statement, but not to the initial value, the variables are also called final blank, in any case, the compiler ensures blank final must be initialized before use, have the safeguard, a class of final data members can be achieved according to the object and differ somewhat, but have to keep the constant features. Here's an example:


public class Test3 { 
 private final String S = "final The instance variables S"; 
 private final int A = 100; 
 public final int B = 90; 
 public static final int C = 80; 
 private static final int D = 70; 
 public final int E; //final blank , An initial value must be assigned when the object is initialized  
 public Test3(int x) { 
   E = x; 
 } 
 private void test() { 
  System.out.println(new Test3(1).A); 
  System.out.println(Test3.C); 
  System.out.println(Test3.D); 
 } 
 public void test2() { 
  final int a;  //final blank , Value is assigned when needed  
  final int b = 4; // Local constants --final Used in the case of local variables  
  final int c; //final blank ,1 No value assigned .  
  a = 3; 
  //a=4;  error , I've already assigned it . 
  //b=2;  error , I've already assigned it . 
 } 
 public static void main(String[] args) { 
  Test3 t = new Test3(2); 
  //t.A=101; // error ,final The value of the variable 1 Once given, it cannot be changed  
  //t.B=91; // error ,final The value of the variable 1 Once given, it cannot be changed  
  //t.C=81; // error ,final The value of the variable 1 Once given, it cannot be changed  
  //t.D=71; // error ,final The value of the variable 1 Once given, it cannot be changed  
  System.out.println(t.A); 
  System.out.println(t.B); 
  System.out.println(t.C); // Object access to static fields is not recommended  
  System.out.println(t.D); // Object access to static fields is not recommended  
  System.out.println(Test3.C); 
  System.out.println(Test3.D); 
  //System.out.println(Test3.E); // error , because E for final blank , Depending on the value of the object . 
  System.out.println(t.E); 
  Test3 t1 = new Test3(3); 
  System.out.println(t1.E); //final Variable blank E Depending on the object  
 } 
}

Another use is to define a method parameter of type final. For primitives, this makes no sense, because primitives pass values when calling a method, and when you change a parameter variable in a method, you change its formal parameters, not its arguments. For object variables, however, it is useful because an object variable is passed as a reference, so changes you make to an object variable in a method also affect the argument object. When you qualify an object variable in a method that cannot be changed as an argument, be sure to explicitly declare it using final.

2. static

static stands for "global" or "static" and is used to modify member variables and member methods. Static static blocks can also be formed, but there is no concept of global variables in THE Java language.

The member variables and member methods modified by static are independent of any object of the class. That is, it does not depend on specific instances of the class and is Shared by all instances of the class. As soon as the class is loaded, the Java virtual machine finds them in the method area of the runtime data area based on the class name. Therefore, the static object can be accessed before any object of its class is created without reference to any object. There are three types of static members of a class: static member variables, static methods, and static code blocks. They all have the following characteristics:

At class load time, code is created and initialized or executed; There's only one of them for each class; All instances of the class can access them.

Static member variables: They are created and initialized after class loading and, because of their unique nature, are typically used for data records of objects, such as reference saving in singleton mode.

Static method: It can be accessed by an object or directly by the class name.

Static code block, static decorated, with curly braces "{... } "enclosed code. This code can use static member variables and methods, which are also called when the class is loaded.

1) static variable

Class member variables can be classified according to whether they are static or not: one is the variable modified by static, called static variable or class variable; The other is variables that are not modified by static, called instance variables. The difference between the two is that for static variables there is only one copy in memory (to save memory), JVM allots memory only once for static variables, performs memory allocation for static variables during class loading, can be accessed directly by the class name (convenient), and can of course be accessed through objects (but this is not recommended). For instance variables, memory is allocated once without creating an instance, and instance variables can have multiple copies in memory without affecting each other (flexible).

2) static method

Static methods can be invoked directly by the name of the class, any instance of also can be called, so a static method cannot be used in this and super keywords, cannot directly access the class's instance variables and instance methods (that is, members of the member variables and methods) without static, static members of a class can only access belongs to static member variables and methods. Because instance members are associated with a particular object! This need to understand, want to understand the truth, not memory!!

Because the static method is independent of any instance, the static method must be implemented and cannot be abstract abstract.

3) static code block

static code block is also called static blocks of code, it is independent of the members of the class in the class static blocks, and you can have multiple, position can be literally put, it is not in any way, JVM loading class will perform these static block of code, if there are multiple static code block, JVM will order in which they appear in the class of execute them in sequence, each block of code will be executed only once. Such as:


public class StaticTest{ 
 private static int a; 
 private int b; 
 private static void testMethod(){ 
  System.out.println("private static method execute..."); 
 } 
 static{ 
  StaticTest.a = 100; 
  System.out.println("execute static codes... a = " + a); 
 } 
 static { 
  StaticTest.a = 3; 
  System.out.println("execute static codes... a = " + a); 
  StaticTest t = new StaticTest(); 
  t.f(); 
  t.b = 1000; 
  System.out.println("b = " + t.b); 
 } 
 public void f() { 
  System.out.println("hhahhahah"); 
 } 
 public static void main(String[] args) 
 { 
  System.out.println(a); 
  StaticTest::testMethod(); 
 } 
} 

Operation results:


execute static codes... a = 100 
execute static codes... a = 3 
hhahhahah 
b = 1000 
3 
private static method execute... 

4) What are static and final1?

When static final1 modifies member variables and methods, it can be simply understood as "global constants"! For variables, this means that once given, the value is immutable and accessible by the class name, which is Shared by all instances of the class. For methods, the representation is not overridden and can be accessed directly by the class name. In particular, there is one problem: for instance constants modified by static and final, the instance itself cannot be changed, but for instance variables of 1 container type (e.g., ArrayList, HashMap), the container variable itself cannot be changed, but the object stored in the container can be modified, which is used a lot in programming. Perhaps with all this said, let's look at an example:


public class TestStaticFinal { 
 private static final String strStaticFinalVar = "aaa"; 
 private static String strStaticVar = null; 
 private final String strFinalVar = null; 
 private static final int intStaticFinalVar = 0; 
 private static final Integer integerStaticFinalVar = new Integer(8); 
 private static final ArrayList<String> alStaticFinalVar = new ArrayList<String>(); 
 private void test() { 
  System.out.println("------------- Value before processing ----------\r\n"); 
  System.out.println("strStaticFinalVar=" + strStaticFinalVar + "\r\n"); 
  System.out.println("strStaticVar=" + strStaticVar + "\r\n"); 
  System.out.println("strFinalVar=" + strFinalVar + "\r\n"); 
  System.out.println("intStaticFinalVar=" + intStaticFinalVar + "\r\n"); 
  System.out.println("integerStaticFinalVar=" + integerStaticFinalVar + "\r\n"); 
  System.out.println("alStaticFinalVar=" + alStaticFinalVar + "\r\n"); 
  //strStaticFinalVar=" Ha ha ha ha ";   // Error, final Said the final state , You can't change the variable itself . 
  strStaticVar = " Ha ha ha ha ";    // Right, static Class variable , Values can change . 
  //strFinalVar=" Ha ha ha ha ";    // error , final Represents the final state, and is defined at the beginning (even if given a number) null ), 1 Once given, it cannot be changed.  
  //intStaticFinalVar=2;     // error , final Represents the final state, and is defined at the beginning (even if given a number) null ), 1 Once given, it cannot be changed.  
  //integerStaticFinalVar=new Integer(8); // error , final Represents the final state, and is defined at the beginning (even if given a number) null ), 1 Once given, it cannot be changed.  
  alStaticFinalVar.add("aaa");   // True, the container variable itself does not change, but the contents of the container do. This rule is very common and has many USES.  
  alStaticFinalVar.add("bbb");   // True, the container variable itself does not change, but the contents of the container do. This rule is very common and has many USES.  
  System.out.println("------------- Values after treatment ----------\r\n"); 
  System.out.println("strStaticFinalVar=" + strStaticFinalVar + "\r\n"); 
  System.out.println("strStaticVar=" + strStaticVar + "\r\n"); 
  System.out.println("strFinalVar=" + strFinalVar + "\r\n"); 
  System.out.println("intStaticFinalVar=" + intStaticFinalVar + "\r\n"); 
  System.out.println("integerStaticFinalVar=" + integerStaticFinalVar + "\r\n"); 
  System.out.println("alStaticFinalVar=" + alStaticFinalVar + "\r\n"); 
 } 
 public static void main(String args[]) { 
   new TestStaticFinal().test(); 
 } 
} 

Operation results:


------------- Value before processing ---------- 
strStaticFinalVar=aaa 
strStaticVar=null 
strFinalVar=null 
intStaticFinalVar=0 
integerStaticFinalVar=8 
alStaticFinalVar=[] 
------------- Values after treatment ---------- 
strStaticFinalVar=aaa 
strStaticVar= Ha ha ha ha  
strFinalVar=null 
intStaticFinalVar=0 
integerStaticFinalVar=8 
alStaticFinalVar=[aaa, bbb] 

Looking at the above example, it is much clearer, but it is important to understand that the objects "loaded" in container type variables modified by static final are modifiable. This is the difference between basic type and class type variables like 1.


Related articles: