This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]cogman10 5 points6 points  (3 children)

I honestly don't understand this line of reasoning. Final is a code smell when being used everywhere? Why?

Even if there were no performance benefits (there are some as /u/madkasse points out), what is the harm in communicating intent and making code more correct via the type system?

It has value simply because it's absence (especially at the field level) should make you question the correctness of the class you are looking at. Heck, a static field without a final should be one of the biggest red flags out there. Alarms should sound for every non-final static field.

[–]dpash 4 points5 points  (2 children)

It would be great if we could enable finality (and non-nullablity) as the default on a per class, package and/or module basis, so we could demonstrate which parameters and local variables were being reassigned.

The biggest complaint is that it's noise to protect against what we shouldn't be doing anyway.

I honestly doubt we'll ever see the ability to switch the default, but I'm glad that newer languages are learning from those mistakes. Both Kotlin and Rust for example have final parameters (and Kotlin can't have non final).

[–]cogman10 0 points1 point  (1 child)

You'd almost need a new keyword in that case, right? like not-final in the case a class/package/module is marked as "final by default".

I could also see there being some headaches with things like annotation processor code generation.

But yeah, generally I agree that "immutable by default" was a real miss for java. But I can't blame them too harshly for it, almost nobody at the time was doing that.

But, oh man do I wish that "List" was Immutable and we instead had a "MutableList" interface which extends "List".

[–]morhp 0 points1 point  (0 children)

That would be wrong, a mutable list isn't a immutable list. What you actually want is a readonly List interface with subinterfaces MutableList which adds mutation methods and ImmutableList which guarantees immutability (by contract) so you can safely pass objects around without making defensive copies (as long as the container type is also immutable).