Final keywords are often misused-they are used excessively when declaring classes and methods, but are not used enough when declaring instance fields. This month, Java practitioner Brian Goetz explored some useful
final
.
Like in its cousin-Cconst
The same keyword, according to the context,final
It indicates different things.final
Keywords can be applied to classes, methods, or fields. When applied to a class, it means that the class can no longer generate child classes. When this method is used, it means that this method cannot be overwritten by the quilt class. When applied to a field, it means that the value of this field is required in each constructor.OnlyAssign a value once and the value remains unchanged after that.
Most Java texts properly describe the usagefinal
Keyword usage and consequence, but rarely provides the related time to use in a standard mannerfinal
And usage frequency. Based on my experience,final
It is used very excessively for classes and methods (usually because developers mistakenly believe that this will improve performance), but it is not used enough when it comes to declaring class instance variables.
Why is this class final?
For developers, declare the classfinal
But it does not explain why this decision was made. This practice is common, especially in open source code projects. After a while, especially if the original developer no longer participates in code maintenance, other developers will always ask "Why Class X is declaredfinal
?". Generally, no one knows that when someone does know or like to guess, the answer is almost always "because it can make it run faster ". The general understanding is to declare a class or Methodfinal
This will make it easier for the compiler to inline method calls, but this understanding is incorrect (or, at least, it is a big story ).
final
Classes and methods can be very difficult to program-they limit your choice to reuse existing code and extend the functionality of existing classes. Sometimes there is a good reason to declare the classfinal
(Such as force immutability ).final
The benefits will be greater than the inconvenience. Performance improvement is almost always a bad reason to undermine good object-oriented design principles. When performance improvement is very small or doesn't improve at all, it is really a poor trade-off method.
Premature Optimization
For performance considerations, methods or classes are declaredfinal
It's a bad idea. There are multiple reasons. First, the early stages of design do not consider Optimization of cyclic computing performance, especially when such decisions may constrain your usefinal
Design. Second, the method or class is declaredfinal
The performance advantage is usually zero. In addition, the complex stateful classes are declaredfinal
It is not conducive to object-oriented design and leads to a large and comprehensive class, because they cannot be easily re-structured into smaller and more compact classes.
Like many myths about Java performance, the class or method is declaredfinal
This error is widely accepted but rarely tested. The argument is: declare methods or classesfinal
This means that the compiler can more actively inline method calls because it knows that at runtime this is the version of the method to be called. But this is obviously incorrect. Only because Class X is compiledfinal
Class y does not mean that class y of the same version will be loaded at runtime. Therefore, the compiler cannot safely inline such cross-class method calls, whether or notfinal
. Only when the method isprivate
The compiler can freely inline it. In this case,final
Keywords are redundant.
On the other hand, the runtime environment and the JIT compiler have more information about the classes actually loaded and can make much better optimization decisions than the compiler. If the runtime environment knows that the class inherited from Y is not loaded, it can safely call the y method, regardless of whether y isfinal
(As long as it can invalidate the JIT compiled code when it subsequently loads the y subclass ). Therefore, the fact is that althoughfinal
The "dummy" runtime optimizer that does not perform any global correlation analysis may be useful, but its use does not actually support too many compile-time optimizations, in addition, intelligent JIT does not need optimization during runtime.
Deja vu-rerecall the register keyword
final
Used for optimization decisions and is not supported by Cregister
The keywords are very similar. This desire for programmers to help the optimizer facilitatesregister
Keyword, but in fact, it is not very useful. As we are willing to believe in other aspects, the compiler is generally better at making code optimization decisions than humans, and more so on the present of the server. In fact, most C compilers completely ignoreregister
Keyword. Earlier C compilers ignored it because these compilers could not be optimized at all; today's compilers ignored it because the compiler could make better optimization decisions without it. In any situation,register
The keyword does not add any performance advantages, and is applied to Java classes or methods.final
The keywords are similar. If you want to optimize your code, please stick to those optimizations that can greatly improve performance, for example, if you use a Valid Algorithm without executing redundant computing, you can leave the cyclic computing optimization to the compiler and JVM.
Use final to preserve immutability
Although the performance is not declaredfinal
But sometimes there are still good reasons to writefinal
Class. The most common isfinal
Ensure that the classes are not changedPersistenceUnchanged. Immutable classes are useful for simplifying the design of Object-oriented Programs-Immutable objects only require less defensive encoding and do not require strict synchronization. You will not build this idea in your code: the class is unchanged, and some people will inherit it in a way that makes it variable. Declare the unchanged classfinal
This ensures that such errors do not sneak into your program.
final
Another reason used for classes or methods is to prevent links between methods from being broken. For example, assume that the implementation of a method of Class X assumes that method M will work in some way. Declare X or mfinal
This will prevent the derived class from redefining m in this way, resulting in abnormal operation of X. Although it may be better to implement X without these internal correlations, it is not always feasible andfinal
This prevents future incompatible changes.
If you must use a final class or method, record why.
In either case, when you have chosen to declare a method or Classfinal
Please record the reason for this. Otherwise, future maintenance personnel may wonder if there are any good reasons for doing so (because it is often unavailable) and will be constrained by your decision, at the same time, you do not know the motivation for doing so to get any benefits. In many cases, the class or method is declaredfinal
The decision is meaningful until the later stages of the development process. At that time, you already have better information about how classes interact and how classes may be inherited. You may find that you do not need to declare the classfinal
Or you can refactor the classfinal
Applies to smaller and simpler classes.
Final Field
final
Fields andfinal
Classes or methods are so different that I think it is unfair to share the same keywords.final
A field is a read-only field. Make sure that its value is instatic final
Field, which is set only once during class initialization. As discussed earlierfinal
Class and method, you will always ask yourself if it is trueYesUsefinal
. Forfinal
Field, you will ask yourself the opposite question-this field is trueYesIs it variable? You may be surprised why this answer is often "not needed ".
Document Description Value
final
Fields have several advantages. For developers who want to use or inherit your class, declare the fieldfinal
There are important documents to illustrate the benefits-This not only helps explain how the class works, but also helps the compiler in strengthening your design decisions. Andfinal
Different methods, Declarationfinal
The field helps the optimizer to make better optimization decisions, because if the compiler knows that the field value will not change, it can safely cache the value in the register.final
The field also provides additional security levels by requiring the compiler to force this field to be read-only.
In extreme cases, the fields of a class arefinal
Primitive orfinal
Reference, then the class itself becomes unchanged-in fact, this is a very convenient situation. Even if this class is not completely unchanged, changing the status of a part of it can greatly simplify development-you do not have to ensure that you are viewingfinal
The current value of the field, or make sure that no one else changes the object status, to keep it synchronized.
So why?final
Is the field used so inadequate? One reason is that it is a little troublesome to correctly use them, especially for object references whose constructors can throw exceptions. Becausefinal
Fields must be initialized only once in each constructor.final
The constructor referenced by the object may throw an exception. The Compiler may report an error saying that the field is not initialized. The compiler is generally more intelligent, enough to find out in two mutually exclusive code branches (for example,if...else
Block ).try...catch
Blocks are generally not so "tolerant ". For example, most Java compilers do not accept the code in Listing 1:
Listing 1. Invalid final-referenced field Initialization
public class Foo { private final Thingie thingie; public Foo() { try { thingie = new Thingie(); } catch (ThingieConstructionException e) { thingie = Thingie.getDefaultThingie(); } }}
|
But they will accept the code in Listing 2, which is equivalent:
Listing 2. Effective initialization of final reference fields
public class Foo { private final Thingie thingie; public Foo() { Thingie tempThingie; try { tempThingie = new Thingie(); } catch (ThingieConstructionException e) { tempThingie = Thingie.getDefaultThingie(); } thingie = tempThingie; }}
|
Limitations of final Fields
final
The field still has some severe restrictions. Although array references can be declaredfinal
But the elements in the array cannot. This means exposurepublic final
Array fields or use their methods to return references to the classes of these fields (for example,DangerousStates
Class) is not unchangeable. Similarly, although the object reference can be declaredfinal
Field, and the object referenced by it may still be variable. If you want to usefinal
You must avoid escaping from your class by referencing arrays or mutable objects. To do this without repeatedly cloning the array, a simple method is to convert the arrayList
For exampleSafeStates
Class:
Listing 3. Exposing array references to make the class variable
// Not immutable -- the states array could be modified by a malicious callerpublic class DangerousStates { private final String[] states = new String[] { "Alabama", "Alaska", ... }; public String[] getStates() { return states; }}// Immutable -- returns an unmodifiable List insteadpublic class SafeStates { private final String[] states = new String[] { "Alabama", "Alaska", ... }; private final List statesAsList = new AbstractList() { public Object get(int n) { return states[n]; } public int size() { return states.length; } }; public List getStates() { return statesAsList; }}
|
Why not inheritfinal
To apply to arrays and referenced objects, similar to C and C ++.const
Is that true? C ++const
The semantics and usage are quite obfuscated, and different things are represented according to the position in the expression. Java architecture designers try to "Rescue" us from this confusion, but unfortunately they have produced some new obfuscation in this process.
Conclusion
To use classes, methods, and fields effectivelyfinal
And some basic principles can be followed. Note that do not tryfinal
It is used as a performance management tool. To improve the performance of your program, there are better and fewer constraints. Used to reflect the basic semantics of your programfinal
: Indicates that these classes will be unchangeable or those fields will be read-only. If you choose to createfinal
Class or method, please make sure that you clearly record why you did this-your colleagues will appreciate it.