|
|
|
Send this page as an email |
|
|
Level: elementary Brian Goetz (brian@quiotix.com), Chief Consultant, quiotix Corp February 11, 2003
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 guidelines on effective use of 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. References
- For more information, see the original article on the developerworks global site.
- ClickDiscussionParticipate in the forum of this article.
- Josh Bloch'sValid Java programming language guideContains a large number of useful tips and guidelines for better code writing.
- Jack Shirazi's Java Performance Tuning website has a large number of performance tuning skills articles, including
final .Note: Many older technical articles providefinal Performance conclusion error suggestions.
- Reynaud waldura provides some usage in the "the final word on the final keyword"
final .
- Earthweb codeguru provides some information about
final Thinking.
- When implementing JSR 133,
final The field semantics will change (to provide more powerful initialization security ).
- InDeveloperworksFind a large number of references related to Java Technology in the Java technology area.
About the author
|
|
|
Brian Goetz is a software consultant and has been a professional software developer for the past 15 years. He is the chief consultant of quiotix, a software development and consulting company in Los Altos, California. Please refer to Brian's published and upcoming articles in popular industry publications. You can contact brian through a brian@quiotix.com. |
|