At least in Java, non-final variables can't be used inside anonymous inner classes. Also, it's easier for me as a developer to read "final" and know that (referential) immutability is guaranteed by the compiler instead of having to read the local scope, which likely contains method calls that may or may not modify that variable.
val and final have stronger meanings when your objects are immutable. True immutability makes reasoning far easier than just referential immutability.
> At least in Java, non-final variables can't be used inside anonymous inner classes.
Aren't those members/fields not variables? If so, then those are effectively global not local, so that's a completely different story – I'm talking strictly about local variables.
> True immutability makes reasoning far easier than just referential immutability.
Yep, immutable types and constant global bindings are great.
I still don't understand why you consider having a compiler-enforced restriction on mutation worse than letting readers figure out what was the developer's intent.
In Java, the only "downside" is having to add "final" as a modifier, which is negligible.
In Scala, the alternative is to declare that variable as "var" instead of "val". When would you ever choose var over val if your object isn't supposed to mutate?
That's just a weird wart of Java – not allowing anonymous inner classes to close over non-final variables was just a cheat to avoid having to implement proper closures; I have no idea what the technical impediments to doing so were when that decision was made, but plenty of languages, including Scala, have real closures.
> In Scala, the alternative is to declare that variable as "var" instead of "val". When would you ever choose var over val if your object isn't supposed to mutate?
It's an extra keyword, an extra complication in the language – one more binary choice to multiply with all the other options. It would be nice to get rid of the distinction altogether.
In Scala, there are both mutable and immutable data structures. Immutable data structures are preferred, however there are some cases in which a dash of mutability can simplify the code, especially in cases where Java inter-op is a must.
val and final have stronger meanings when your objects are immutable. True immutability makes reasoning far easier than just referential immutability.