Document directory
From jdk1.0 to today, Java technology has undergone tremendous technological changes after more than a decade of development. however, the definition of final variables has not changed since its birth, that is, it has been representing its original meaning for more than a decade. unfortunately, after more than a decade, 90% of people still do not understand the true meaning of it, nor have they published an article, including all the introductions I have seen.
Java books (including tkj) are not clear. I believe some authors understand this, but none of them tell readers clearly. Chinese netizens
Most people have been beaten by an article about <talking about final, finalized, finally> in Java ).
The definition of final variables is not complex, that is, once initialized, variables cannot point to other objects. In C ++, they are a const pointer, and
It is not a pointer to the const variable. The const pointer means that it can only always point to the address at the time of initialization, but the object in that address itself
The pointer to the const variable indicates that the object itself cannot be modified.
For example:
- Final stringbuffer sb = new stringbuffer ("axman ");
- SB = new stringbuffer ("Sager"); // error. SB cannot point to other objects.
- SB. append ("was changed! "); // The earth object to which sb points can be modified.
Let's first talk about final variable initialization:
Many articles have said this: the initialization can be in two places: one is its definition, and the other is in the constructor. Either of them can be selected.
Nonsense!
Final variables can be initialized at any place where they can be initialized, but can only be initialized once. Once initialized, they cannot be assigned again.
Value (re-pointing to other objects), must be explicitly initialized as a member variable, while as a temporary variable, you can only define and do not initialize (of course, cannot reference)
Even as a member variable in a class, it can also be initialized in the initialization block, so "the initialization can be in two places. One is its definition,
Second, in the constructor, either of the two can be "Incorrect.
As a member variable, the final field can be designed as a non-variable class, which is a required condition but not a sufficient condition. At least it can ensure that the field is not
It will be changed in the form of setxxx (), but it cannot be ensured that the field itself is not modified (unless the field itself is also a constant class );
For final variables of method parameters:
If the variables of method parameters are defined as final, more than 90% of the articles say, "when you do not need to change the object variables used as parameters in methods, make it clear
Using final statements will prevent you from accidentally modifying the variables outside the calling method. "
Nonsense!
I don't know whether this modification refers to re-assigning the value or modifying the object itself, but in either case, the above statement is wrong.
If the value is re-assigned, then:
- Public static void test (INT [] X ){
- X = new int [] {1, 2, 3 };
- }
- Int [] out = new int [] {4, 5, 6 };
- Test (out );
- System. Out. println (out [0]);
- System. Out. println (out [1]);
- System. Out. println (out [2]);
Call test (out); in any case, it will not affect the out variable. It doesn't make sense if you add final. Final will only force the Method
Declare one more variable name, that is, change x = new int [] {1, 2, 3}; to int y = new int [] {1, 2, 3 }; nothing else actually makes sense.
If it is to modify the object itself:
- Public static void test (final int [] X ){
- X [0] = 100;
- }
- Int [] out = new int [] {4, 5, 6 };
- Test (out );
- System. Out. println (out [0]);
Can't you modify the final modification? Therefore, the final in the method parameters is used to avoid affecting the variables outside the called method.
So why should we add final to the parameter? In fact, adding final to method parameters is the same as adding final to method variables, that is,
Ensure the call consistency when passed to the internal class:
- Abstract class absclass {
- Public abstract void M ();
- }
Now, if I want to implement an anonymous call to absclass in a method, we should:
- Public static void test (final string s ){
- // Or final string S = "axman ";
- Absclass c = new absclass (){
- Public void M (){
- Int x = S. hashcode ();
- System. Out. println (X );
- }
- };
- // Other code.
- }
- // The code is actually compiled:
- Public static void test (final string s ){
- // Or final string S = "axman ";
- Absclass c = new absclass (s ){
- Private final string S;
- Public absclass (string s ){
- This. S = s;
- }
- Public void M (){
- Int x = S. hashcode ();
- System. Out. println (X );
- }
- };
- // Other code.
- }
That is, the variable of the external class is passed to the private member of the internal class as the parameter of the constructor.
If there is no final, then:
- Public static void test (string s ){
- // Or string S = "axman ";
- Absclass c = new absclass (){
- Public void M (){
- S = "other ";
- }
- };
- System. Out. println (s );
- }
- // It will be compiled:
- Public static void test (string s ){
- // Or string S = "axman ";
- Absclass c = new absclass (s ){
- Private final string S;
- Public absclass (string s ){
- This. S = s;
- }
- Public void M (){
- S = "other ";
- }
- };
- System. Out. println (s );
- }
- // The S of the internal class points to "other" and does not affect the test parameter or the S defined externally. What you see
- Public static void test (string s ){
- // Or string S = "axman ";
- Absclass c = new absclass (){
- Public void M (){
- S = "other ";
- }
- };
- System. Out. println (s );
- }
The syntax is a second, which is changed in the internal class, but the result is printed and you think it is the same s, but it is still the original "axman ",
Can you receive such results?
Therefore, final restricts the consistency of two different variables in syntax.
========================================================== ========================================================== ======================================
Another article
Final
Final is not commonly used in Java, but it provides functions such as defining constants in C language, final also allows you to control whether your members, methods, or a class can be overwritten or inherited. These features enable final to play an indispensable role in Java, it is also one of the keywords that must be known and mastered when learning Java.
Final member
When you define a variable in a class and add the final keyword before it, this variable cannot be changed once initialized, the unchangeable meaning here is that its value is immutable for the basic type, and its reference for the object variable cannot be changed. It can be initialized in two places. One is its definition, that is, it is assigned a value directly when the final variable is defined, and the other is in the constructor. You can only choose one of these two places, either give a value at the time of definition, or give a value in the constructor, not both at the time of definition, in the constructor, another value is given. The following code demonstrates this point:
- ImportJava. util.List;
- ImportJava. util.Arraylist;
- ImportJava. util.Shortlist;
- Public ClassBat {
- FinalPi = 3.14;// The address value is assigned at the time of definition.
- Final IntI;// Because Initialization is required in the constructor, no value can be given here
- Final ListList;// This variable is the same as the above variable.
- BAT (){
- I = 100;
- List =New Shortlist();
- }
- BAT (IntII,ListL ){
- I = II;
- List = L;
- }
- Public Static VoidMain (String[] ARGs ){
- Bat B =NewBAT ();
- B. List. Add (NewBAT ());
- // B. I = 25;
- // B. List = new arraylist ();
- System. Out. println ("I =" + B. I + "list type:" + B. List. getclass ());
- B =NewBAT (23,New Arraylist());
- B. List. Add (NewBAT ());
- System. Out. println ("I =" + B. I + "list type:" + B. List. getclass ());
- }
- }
This program demonstrates the general usage of final. Here we use the initialization method in the constructor, which gives you a little flexibility. As shown in the two overloaded constructors of BAT, the first default constructor will provide you with the default value. The overloaded constructor will initialize the final variable based on the value or type you provided. However, sometimes you don't need this flexibility. You just need to set the value at the time of definition and never change. In this case, you don't need to use this method. There are two lines of statements commented out in the main method. If you remove the comment, the program will not be able to compile. This is to say, whether it is the value of I or the type of list, once initialized, it cannot be changed. However, B can specify the I value or list type through reinitialization. This is shown in the output:
I = 100 list type: Class java. util. Category list
I = 23 list type: Class java. util. arraylist
Another method is to define the final parameter in the method. For variables of the basic type, this method has no practical significance, because the variables of the basic type are passed values when calling the method, that is to say, you can change this parameter variable in the method without affecting the call statement. However, it is very practical for the object variable because the object variable is passed with its reference during transmission, in this way, your modification to the object variable in the method will also affect the object variable in the call statement. When you do not need to change the object variable used as the parameter in the method, use final to declare it, it will prevent you from accidentally modifying the call method.
In addition, when the internal class in the method uses the variable in the method, this parameter must be declared as final for use, as shown in the following code:
- Public ClassInclass {
- VoidInnerclass (Final StringStr ){
- ClassIclass {
- Iclass (){
- System. Out. println (STR );
- }
- }
- Iclass Ic =NewIclass ();
- }
- Public Static VoidMain (String[] ARGs ){
- Inclass Inc =NewInclass ();
- Inc. innerclass ("hello ");
- }
- }
Final Method
If you declare the method as final, it means that you already know that the function provided by this method has met your requirements and does not need to be extended, this method cannot be overwritten by any class inherited from this class, but inheritance can still inherit this method, that is, it can be used directly. In addition, there is a mechanism called inline, which enables you to directly Insert the method subject into the call when calling the final method, rather than performing routine method calls, such as saving breakpoints, this may improve the program efficiency. However, when your method subject is very large, or you call this method in multiple places, your calling subject code will expand rapidly, which may affect the efficiency. Therefore, use final for method definition with caution.
Final class
When using final on a class, you need to consider it carefully. Because a final class cannot be inherited by anyone, it means that this class is a leaf class in an inheritance tree, in addition, such designs have been considered perfect without modification or expansion. For members in the final class, you can define it as final or not final. For methods, because the class is final, they naturally become final. You can also explicitly add a final to the methods in the final class, but this is obviously meaningless.
The following program demonstrates the usage of the final method and final class:
- Final Class Final{
- Final StringSTR = "final data ";
- Public StringStr1 = "non final data ";
- Final Public VoidPrint (){
- System. Out. println ("final method .");
- }
- Public VoidWhat (){
- System. Out. println (STR + "/N" + str1 );
- }
- }
- Public ClassFinaldemo {// Extends final cannot be inherited
- Public Static VoidMain (String[] ARGs ){
- FinalF =New Final();
- F. What ();
- F. Print ();
- }
- }
It can be seen from the program that there is almost no difference between the use of final classes and common classes, but it loses its inherited features. The difference between the final method and the non-final method is also difficult to see from the program line, just remember to use it with caution.
Application of final in Design Mode
In the design pattern, there is a pattern called the immutable pattern. in Java, this pattern can be easily implemented through the final keyword. It explains the program bat used by final members. java is an example of the unchanged mode. If you are interested in this, you can refer to the explanation in the book "Java and mode" written by Dr. Yu Hong.
So far, the use of this, static, supert and final has been completed. If you have been able to roughly express the differences and usage of these four keywords, it means that you have mastered it. However, nothing in the world is perfect. Java provides these four keywords, which brings great convenience to the programming of programmers, but it does not mean that you should use them everywhere, once an abused program is reached, it is counterproductive. Therefore, you must carefully consider it when using it.