I have not been using the final
Java keyword
when I was an inexperienced software developer.
This was a mysterious keyword to me for a long time.
Especially for local variables inside a method, I asked myself:
why would immutable values make sense?
There are opinions on the web
proving that
I am not the only one
asking this question.
In this article I will present some code snippets that may
shed a little light on immutability. It is not easy to understand
why we should use final
as much as possible.
The realization comes only over time when you have seen
a lot of the buggy code that is around everywhere.
Long methods are the home of mutability mistakes.
A User Story
The Java source code below implements the following story:
- it is not raining, and
- either it is not cold or no wind is blowing
- a park is in reach
Seems to be an application for travellers ...
Buggy Implementation
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | private boolean shouldGoWalking( boolean raining, boolean cold, boolean windBlowing, Park[] parks) { boolean goWalking = false; if (raining == false && (cold == false || windBlowing == false)) goWalking = true; for (Park park : parks) if (park.isInReach()) goWalking = true; return goWalking; } |
It is easy to see that this code doesn't work as expected. The problem starts at line 12. When a park is in reach, the weather simply is ignored. S... happens.
How can we detect such bugs quickly? You got it: make everything final (even the parameters). I wouldn't even try to understand the code before doing this.
7 | final boolean goWalking; |
Consequence is that you can assign a value just once. The compiler will show you immediately all places where the variable is assigned, and there you have the bug.
Correct Implementation
1 2 3 4 5 6 7 8 9 10 11 12 13 | private boolean shouldGoWalking( final boolean raining, final boolean cold, final boolean windBlowing, final Park[] parks) { final boolean acceptableWeather = (raining == false && (cold == false || windBlowing == false)); final boolean parkInReach = Arrays.stream(parks).anyMatch(p -> p.isInReach()); return acceptableWeather && parkInReach; } |
I made two steps in one:
- give all involved logics descriptive names:
acceptableWeather
andparkInReach
- make all local variables constant through the
final
access modifier
This is also much better readable code.
Most mutability bugs I've seen happened with String
and boolean
variables.
Conclusion
Actually it is quite easy to realize the value of immutability:
- → functional languages do not allow mutable variables
- → functional languages deliver the most robust implementations you can get
If you sum this up, you find out that you should use as much
immutable class fields, parameters and local values as possible.
The final
keyword does not cutter code.
It proves that you were thinking while programming.
Keine Kommentare:
Kommentar veröffentlichen