Reputation: 7663
After I use IntelliJ to inspect my code, hundreds of "Declaration can have final modifier" warnings are issued. To resolve these warnings, I essentially need to turn most of my variables into final, and the following is one typical example. This provokes me to think that I should make member variables as 'final' by default. In most cases, members, especially container classes (i.e. List or Set) ,won't get changed once they are assigned. They change internally by inserting or removing elements from them, but the references to them won't change.
public class Attribute {
private final Insight insight;
private final Attribute attribute;
private final List<String> names;
public Attribute(Insight insight, Attribute attribute) {
attribute = attribute;
insight = insight;
names = new ArrayList<>();
}
}
Does it make sense to make most variables as final by default in design classes? Is it the case that most member variables can be defined as 'final' in Java?
Upvotes: 3
Views: 1161
Reputation: 10084
Does it make sense that I have to make most of my variables final?
Yes. But the reasons that it does are probably different than the reasons that were imagined when the language came to life in the 1990s.
In the 90s, CPUs in desktop computing were single core, single thread. The final
modifier was mostly used at that time as a means to achieve similar semantics to the const
s of C.
But final
has more importance now that programs run on multi-threaded, multi-core CPU's. In general, it is advantageous wherever possible to restrict and/or simplify the state space of objects that may be shared in a concurrent environment. This was not always well understood when the language was in its early days. The Calendar
class in early Java (which persisted until Java 8) had a very complex state space with equally complex state transitions that made using Calendar
objects in concurrent environments more difficult than it had to be. In his book, Effective Java (2nd Ed.), Joshua Bloch even said that few people really understood the state space of the Calendar
class.
When instance fields are final, the number of state transitions they can undergo is necessarily restricted. This is a good thing because this makes objects in a concurrent environment simpler to reason about. The ultimately simple object is an immutable object in which all instance fields are initialized in their final form and cannot be changed. Such objects are very simple to use in concurrent environments because...
As a result, immutable objects can be freely shared among an arbitrarily large number of threads.
TL;DR: Final instance fields make your objects simpler and easier to reason about. The expected effects are code that is simpler to understand and cheaper to maintain. Bloch recommends that you make any instance field final
whenever you can.
Upvotes: 1
Reputation: 10184
While it makes sense that every member field that is not going to change the reference it is initialized with, should be declared final, in your case though, you can use some other best practices. You might want to provide setters
(and getters
) for your member attributes unless they are not modifiable after initialization. If you provide setters
, IntelliJ won't complain. Also, you can suppress those warnings by following the instructions laid out here.
The short answer is
final
.Upvotes: 0
Reputation: 62789
If one were to redesign Java today variables should probably default to private and final rather than package and mutable.
Mutable variables are sometimes necessary but whenever possible you should prefer final, and I can't really think of many legitimate reasons to make variables anything but private.
Things might be different for different target environments but Java is designed to make good readable/maintainable long-lived code, and considering this they just made a few poor decisions on defaults.
But it's an old language and we didn't know as much as we do now. live and learn.
ps: I'd also throw out checked exceptions if I was in charge... probably a good thing I'm not.
Upvotes: 3
Reputation: 183
If you think about most applications in a real world environment, most of the variables can be final. There are lots of benefits to declaring them final. But I would suggest you to do it as a habit rather than using IDE suggestions and features. As a habit always think of the variables whether they need to mutate or not, if not as part of defining the variable just add final. This habit makes you write finals independent of IDE suggestions. Most IDEs are pretty good at code completion, but you never know. PS: Do keep in mind inheritance of your objects when you make this a habit.
I accidentally declared a final on method once out of habit and paid a price for it :-).
Upvotes: 1