Most new developers these days learn how to program in an object-oriented language such as Java and many people have learned Java as one of several programming languages over the course of their career. Java has some unique characteristics that are not always found in other languages and the final keyword is one of them. Since we are not accustomed to using it, it may be misused or misunderstood. Some developers over-use it because they think it will enhance performance, other underutilize this powerful tool where it could be useful because they don’t understand it. In this article I will talk about the usage of the final keyword and some best practices for guidance on when and how to use final.
The final keyword has a basic similarity to the const keyword in C, where it can mean different things depending on its context and what it is applied to. final can be used with classes, methods or fields and has some basic rules for each:
- When applied to classes, the class cannot be subclassed
- When applied to methods, the method cannot be overridden by a subclass
- When applied to fields, the field’s value must be assigned exactly once in each constructor and cannot change after that.
While most developers can look through Java texts and documentation to find an explanation of the rules of using final, let’s look at some situations when using it may or may not be the best idea.
When Should My Class Be Final?
It is a common occurrence to see classes declared as final but no indication as to why the decision was made. Many developers make a class final because they believe this is an optimization step and makes the class perform better. This is a common misconception and declaring classes or methods as final does not make it easier for the complier to make calls to that member. In fact, making classes and methods final can create a significant amount of inconvenience when programming since they limit the number of options for reusing existing code and extending the functionality of classes.
While sometimes a class is made final for a good reason, such as to enforce immutability (more on this below), the benefits should outweigh the inconvenience since it is a very significant cost. It is highly unlikely that you are getting any performance benefit from using final on your class and it doesn’t promote good object-oriented design principles, which is a bad trade off.
The misconceptions that final increases the speed of the complier to make calls to your class is invalid and dangerous since developers do not often understand the implications of this decision. The basis for this centers around the idea that declaring a method or class as final means the complier can call it inline because it knows there can be no further extension or overrides on the method or class. This simply isn’t true. It is best to leave this form of optimization up to the JIT complier, which has much more information about which classes are loaded and can make better decisions in this situation than the developer. Using final may actually hinder a good JIT from performing run-time optimizations.
Avoid Premature Optimization
Performance enhancement maneuvers, especially at the start of a project, are usually a bad idea for several reasons:
- 1. Early stage design is the wrong time to start thinking about code, especially code that hasn’t been written.
- 2. These decisions can constrain the design
- 3. The performance benefit gained in using a keyword like final is minimal
- 4. Creating situations that require complicated, stateful classes is contrary to good OO design concepts.
- 5. Over-optimization usually leads to bloated classes because they cannot be refactored into smaller, more usable, classes.
It is best to wait until you are further into the development process to decide whether or not to make a class or method final so you will have more information on how the interactions in your program will be affected. You may not need that final keyword after all.
When Should I Use Final?
We have discussed why you should not use final for your class, but there are several good reasons and situations in which final is a good choice to use on your class. The most common reason is to preserve immutability; final guarantees that classes intended to be immutable, stay immutable. These classes are a staple of object-oriented design and are sometimes necessary for simplifying your program design. Immutable objects do not require as much defensive programming and have relaxed synchronization requirements. Using final can ensure that a class is not later extended by someone in a way that makes it mutable.
A second common reason to use final is to prevent linkages between methods from being broken. Since methods cannot be redefined when declared final, you can ensure to one method the behavior of another method will always be the same. Other developers would not be able to create new implementations of your method in derived classes which would can unexpected or inappropriate behavior in another method. Using final prevents any modifications in the future and can keep these internal dependencies intact.
No matter your reasoning for using final on your class or method, you should always document your thought process and reasoning for the decision. Future developers of your code may not understand why the final keyword has been applied or why it is best in this situation. Good documentation is the key to good coding and it will definitely help for future maintainers so they do not arbitrarily remove the final out of confusion.
Can I Use final Fields?
Using final on fields is almost a different animal entirely from classes or methods.final fields create a read-only field that is guaranteed to have its value set only once in the constructor.final fields have many benefits that can be used to extend your class as well as documentation benefits. These fields can be used to explain how a class works and the complier will enforce these design decisions. Unlike with methods and classes, using final for fields does help the compiler make better optimization decisions because it knows the field value is not going to change. This value can then be cached in the register.
Another added benefit is when you have a class whose fields are all final references to immutable objects or finalprimitives. In this case, the class becomes immutable itself, which can be a handy situation since the class is not whole immutable but to not allow changes to certain parts of the class can simplify your design.
There are still some limitations and downsides to using final fields:
- Array references can be declared final but the elements in the array cannot
- An object reference may be declared as a final field but the object itself may still be mutable
You should ask yourself the same questions when applying final to fields as you do with classes and methods. Does this field really need to be mutable? You might surprise yourself to find out the answer is no.
I hope you have found a new outlook on the final keyword as well as some basic guidelines for using it in the future. The final keyword does have its place in classes, methods and fields as long as it is thought-out and appropriate for the situation. Don’t try to use final for optimization purposes or to increase performance since there are many other ways you can try that would be more effective. If you do make the decision to use final in your programs, document your decision clearly and give your point of view on the problem. This will help future maintainers understand its purpose.
Help us spread the word!
If you liked this article, consider enrolling in one of these related courses:
|Oct 20-23||Introduction to Java Programming|
|Jan 05-08||Introduction to Java Programming|
|- Classroom - Online|