When it comes to the final keyword, it's probably a lot of people who are not unfamiliar with the final keyword when using anonymous internal classes. In addition, the string class in Java is a final class, so today we'll look at the use of the final keyword.
First, the basic usage of final key words
In Java, the final keyword can be used to decorate classes, methods, and variables (including member variables and local variables). Here's a look at the basic usage of the final keyword in three ways.
1. Decoration class
when a class is decorated with final, it indicates that the class cannot be inherited. In other words, if a class you never let him inherit, you can use final to decorate. Member variables in the final class can be set to final as needed, but note that all member methods in the final class are implicitly specified as the final method.
When using the final modifier class, be careful to choose, unless the class is not intended to be inherited later or for security reasons, try not to design the class as the final class.
2. Modification method
The following is part of the fourth edition of Java Programming thought, page 143th:
There are two reasons for using the final method. The first reason is to lock the method in case any inherited class modifies its meaning, and the second reason is efficiency. In earlier versions of Java implementations, the final method was converted to inline invocation. However, if the method is too large, you may not see any performance gains from inline calls. In the recent Java release, these optimizations do not need to be made using the final method. “
Therefore, the method is set to final only if you want to explicitly prohibit the method from being overwritten in the subclass. that is, the final method of the parent class is not covered by the quilt class, that is, the subclass is not able to exist the same way as the parent class.
The final decorated method means that this method is already a "final, final" meaning, that is, this method cannot be overridden (you can overload multiple final-decorated methods). one thing to note here is that because the overriding premise is that subclasses can inherit this method from the parent class, if the final decorated method in the parent class has access control permission to private, it will cause the subclass to not inherit directly into this method, so The same method names and parameters can be defined in the subclass at this point, and the rewrite is no longer contradictory to final, but the new method is redefined in the subclass. (Note: The private method of the class is implicitly specified as the final method.) )
1 Public classBextendsA {2 3 Public Static voidMain (string[] args) {4 5 }6 7 Public voidGetName () {8 9 }Ten } One A classA { - - /** the * Because of the private adornment, the subclass cannot inherit this method, so the GetName method in the subclass is redefined, - * methods that belong to the subclass itself, compile normally - */ - Private Final voidGetName () { + - } + A /*because Pblic is modified, subclasses can inherit to this method, resulting in overriding the final method of the parent class, compiling an error at Public final void GetName () { - - } - */ -}
3. Modifier variables
The modified variable is the most used place in final use, and it is also the focus of this article.
The final member variable represents a constant, which can only be assigned once, and the value will no longer change after the value is assigned.
When final modifies a base data type, the value that represents the base data type cannot change after initialization, and if final decorates a reference type, it cannot point to another object after it is initialized, but the contents of the object pointed to by the reference can vary. is essentially one thing, because the value of the reference is an address, the final requirement value, that is, the value of the address does not change.
final modifies a member variable (property) that must be displayed for initialization. There are two types of initialization , one is initialized at the time of the variable declaration, and the second is to not assign the initial value when declaring the variable, but to assign an initial value to the variable in all the constructors of the class where the variable resides.
When the parameter type of a function is declared final, the parameter is read-only. that is, you can read it using this parameter, but you cannot change the value of the parameter.
As an example:
In the above section of the code, the re-assignment of the variables I and obj is an error.
Second, in-depth understanding of the final keyword
After understanding the basic usage of the final keyword, let's look at where the final keyword is easy to confuse.
1. What is the difference between a class's final variable and a normal variable?
When you use final action on a member variable of a class, the member variable (note is the member variable of the class, the local variable needs to be guaranteed to be initialized before use) must be assigned in the definition or constructor, and once the final variable is initialized, it can no longer be assigned a value.
So what is the difference between a final variable and a normal variable? Let's take a look at the following example:
1 Public classTest {2 Public Static voidMain (string[] args) {3String a = "Hello2"; 4 FinalString b = "Hello"; 5String d = "Hello"; 6String C = B + 2; 7String E = d + 2; 8System.out.println ((A = =c)); 9System.out.println ((A = =e)); Ten } One}
Output result: true, False
We can first think about the output of this problem. Why the first comparison result is true, and the second compares the result to Fasle. This is the difference between the final variable and the normal variable, when the final variable is the base data type and the string type, if you can know its exact value during compilation, the compiler will use it as a compile-time constant. That is, where the final variable is used, it is equivalent to the constant that is accessed directly, and does not need to be determined at run time. This is a bit like a macro substitution in C language. So in the preceding section of code, because the variable B is final decorated, it is treated as a compiler constant, so where B is used, the variable b is replaced directly with its value. The access to variable D needs to be linked at run time. Presumably the difference should be understood, but note that the compiler does this only if the final variable value is known exactly during compilation, as the following code does not optimize:
1 Public classTest {2 Public Static voidMain (string[] args) {3String a = "Hello2"; 4 FinalString B =Gethello ();5String C = B + 2; 6System.out.println ((A = =c)); 7 8 } 9 Ten Public StaticString Gethello () { One return"Hello"; A } -}
The output of this code is false. one thing to note here is this: don't assume that some data is final and you know its value at compile time, and with variable b we know that it's initialized with the Gethello () method, and he's going to know its value at run time.
2. Is the object content of the final modified reference variable variable?
In the above mentioned the final modified reference variable once the initialization of the assignment can no longer point to other objects, then the reference variable point to the contents of the object is variable? Look at the following example:
1 Public classTest {2 Public Static voidMain (string[] args) {3 FinalMyClass MyClass =NewMyClass ();4SYSTEM.OUT.PRINTLN (+ +)myclass.i); 5 6 } 7 } 8 9 classMyClass {Ten Public inti = 0; One}
This code can be successfully compiled and has output results, the output is 1. This means that after the reference variable is final decorated, it cannot point to another object, but the contents of the object it points to are mutable.
3, final parameters of the problem
In practice, we can modify a member variable, a member method, a class, or a parameter, if a parameter is final, in addition to the final modifier, which means the parameter is immutable. If we modify this parameter in the method, the compiler will prompt you: The final local variable I cannot be assigned. It must is blank and not using a compound assignment. Look at the following example:
1 Public classtestfinal {2 3 Public Static voidMain (string[] args) {4Testfinal testfinal =Newtestfinal ();5 inti = 0;6 Testfinal.changevalue (i);7 System.out.println (i);8 9 }Ten One Public voidChangeValue (Final inti) { A //The final parameter cannot be changed - //i++; - System.out.println (i); the } -}
The value of the variable I cannot be changed in the method after the above code changevalue the parameter I in the method with the final decoration. It is worth noting that the method changevalue and the variable I in the Main method are not a variable at all, because the Java parameter pass takes the value pass, and for the basic type of variable, it is equivalent to copying the variable directly. So even without final modification, changing the value of the variable I within the method does not affect the I outside of the method.
Let's look at the following code:
1 Public classtestfinal {2 3 Public Static voidMain (string[] args) {4Testfinal testfinal =Newtestfinal ();5StringBuffer buffer =NewStringBuffer ("Hello");6 testfinal.changevalue (buffer);7 System.out.println (buffer);8 9 }Ten One Public voidChangeValue (FinalStringBuffer Buffer) { A //The final modifier references a parameter of the type, and can no longer point it to another object, but the content to which it points is subject to change. - //buffer = new StringBuffer ("HI"); -Buffer.append ("World"); the } -}
Running this code will reveal that the output is HelloWorld. It is clear that the final modification can no longer allow buffer to point to other objects, but the contents of the object to which buffer points are changed. Now suppose a situation, if final is removed, what will the result be? Look at the following code:
1 Public classtestfinal {2 3 Public Static voidMain (string[] args) {4Testfinal testfinal =Newtestfinal ();5StringBuffer buffer =NewStringBuffer ("Hello");6 testfinal.changevalue (buffer);7 System.out.println (buffer);8 9 }Ten One Public voidchangevalue (stringbuffer buffer) { A //buffer points back to another object -Buffer =NewStringBuffer ("Hi"); -Buffer.append ("World"); the System.out.println (buffer); - } -}
Operation Result:
Hiworldhello
As can be seen from the running results, the final is removed, and in the ChangeValue buffer points to other objects, and does not affect the buffer in the main method, because Java is the value of the pass, for the reference variable, passed the reference value, This means that the argument and the parameter point to the same object at the same time, so having the parameter point back to another object has no effect on the argument.
Summary of the usage of the "Java Learning Note 20" final keyword in Java inheritance