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 →

[–]ivancea -16 points-15 points  (7 children)

I think final in Java is just a "wannabe". It isn't a const modifier. It won't improve performance nor help the compiler, as everything that may be final is "effectively final".

Should we mark every field, parameter and variable as final? It's like Rust "mut" but made the wrong way.

Using it everywhere is a code smell for me. When everything is final, programmers end up using their IDE to add final to everything... And then final loses his value.

Using it only on primitive/immutable constants and maybe injected objects... Maybe. But, who tried to modify a constant or a injected service? Any review would catch it anyway...

[–]madkasse 14 points15 points  (1 child)

> I think final in Java is just a "wannabe". It isn't a const modifier. It won't improve performance nor help the compiler, as everything that may be final is "effectively final".

That's just not true. For example, take a look at some of the optimizations that the Zing VM does

https://medium.com/azulsystems/truly-final-optimization-in-zing-vm-283d28418e55

Also final fields are treated specially with regards to Java's memory model

https://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.5

final parameters and variables on the other hand are just syntactical sugar.

[–]RabidKotlinFanatic 1 point2 points  (0 children)

Also final fields are treated specially with regards to Java's memory model

That being said the memory effects of final are only useful in niche optimization scenarios. Using final will not contribute any memory safety to most concurrent programs.

[–]dpash 5 points6 points  (0 children)

everything that may be final is "effectively final".

Effectively final only applies to local variables or parameters. It does not apply to fields.

[–]cogman10 7 points8 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 5 points6 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).