Java Theory and Practice: Is that your final answer?

Source: Internet
Author: User
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-CconstThe same keyword, according to the context,finalIt indicates different things.finalKeywords 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 usagefinalKeyword usage and consequence, but rarely provides the related time to use in a standard mannerfinalAnd usage frequency. Based on my experience,finalIt 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 classfinalBut 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 MethodfinalThis will make it easier for the compiler to inline method calls, but this understanding is incorrect (or, at least, it is a big story ).

finalClasses 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 ).finalThe 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 declaredfinalIt'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 usefinalDesign. Second, the method or class is declaredfinalThe performance advantage is usually zero. In addition, the complex stateful classes are declaredfinalIt 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 declaredfinalThis error is widely accepted but rarely tested. The argument is: declare methods or classesfinalThis 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 compiledfinalClass 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 isprivateThe compiler can freely inline it. In this case,finalKeywords 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 althoughfinalThe "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
finalUsed for optimization decisions and is not supported by CregisterThe keywords are very similar. This desire for programmers to help the optimizer facilitatesregisterKeyword, 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 ignoreregisterKeyword. 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,registerThe keyword does not add any performance advantages, and is applied to Java classes or methods.finalThe 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 declaredfinalBut sometimes there are still good reasons to writefinalClass. The most common isfinalEnsure 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 classfinalThis ensures that such errors do not sneak into your program.

finalAnother 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 mfinalThis 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 andfinalThis 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 ClassfinalPlease 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 declaredfinalThe 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 classfinalOr you can refactor the classfinalApplies to smaller and simpler classes.

Final Field
finalFields andfinalClasses or methods are so different that I think it is unfair to share the same keywords.finalA field is a read-only field. Make sure that its value is instatic finalField, which is set only once during class initialization. As discussed earlierfinalClass and method, you will always ask yourself if it is trueYesUsefinal. ForfinalField, 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
finalFields have several advantages. For developers who want to use or inherit your class, declare the fieldfinalThere 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. AndfinalDifferent methods, DeclarationfinalThe 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.finalThe 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 arefinalPrimitive orfinalReference, 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 viewingfinalThe current value of the field, or make sure that no one else changes the object status, to keep it synchronized.

So why?finalIs 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. BecausefinalFields must be initialized only once in each constructor.finalThe 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...elseBlock ).try...catchBlocks 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
finalThe field still has some severe restrictions. Although array references can be declaredfinalBut the elements in the array cannot. This means exposurepublic finalArray fields or use their methods to return references to the classes of these fields (for example,DangerousStatesClass) is not unchangeable. Similarly, although the object reference can be declaredfinalField, and the object referenced by it may still be variable. If you want to usefinalYou 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 arrayListFor exampleSafeStatesClass:

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 inheritfinalTo apply to arrays and referenced objects, similar to C and C ++.constIs that true? C ++constThe 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 effectivelyfinalAnd some basic principles can be followed. Note that do not tryfinalIt 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 createfinalClass or method, please make sure that you clearly record why you did this-your colleagues will appreciate it.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.