final in Java does not guarantee immutability.  It would be AWESOME if it did 
but all it guarantees is that the variable cannot be reassigned. In most cases 
the variable points to an object’s location (memory address), so you can still 
call methods on it, e.g.

final var = new Foo();
var.mutateState();

final variables like these are in no way thread safe. To make objects 
immutable, the objects themselves need to follow a pattern that guarantees 
that.  Something like the ValueObject 
<https://martinfowler.com/bliki/ValueObject.html> pattern.

Mutability may well be the enemy, but I don’t think this is the construct that 
gets us much/if any closer.

In local variables and parameters final feels like noise to me, and in fact may 
make things more difficult to reason about, if we start assuming variables with 
final are thread safe.

But I may be missing something.  I am more curious to see how we come to 
consensus on something like this, because the worst outcome from all this will 
be to have some folks actively adding final and some actively removing it, 
which will add noise to PRs and to the code.  And once we reach consensus, how 
do we enforce somethings like this? ./gradlew spA?

> On Jun 17, 2019, at 8:55 PM, Jacob Barrett <jbarr...@pivotal.io> wrote:
> 
> I too am in camp final too. You could say `final boolean useFinal = true`. 
> For all the same reasons Bill stated below.
> 
>> On Jun 17, 2019, at 5:33 PM, Bill Burcham <bburc...@pivotal.io> wrote:
>> 
>> The final keyword is not redundant—quite the opposite—it's extremely 
>> valuable.
>> 
>> Local variables are not, in general, final, unless you declare them as such. 
>> That being the case, it is not redundant to declare local variables "final".
>> 
>> What the compiler will do for you, is _if_ it can ensure that a local 
>> variable (or method parameter) is never modified (after initialization) then 
>> that variable is treated as "effectively final". Variables that are 
>> explicitly declared final, or are determined to be "effectively final" may 
>> be referenced in lambdas. That's a nice thing.
>> 
>> I would like to offer a counter-recommendation: final should be the default 
>> everywhere for fields, for method parameters (on classes, not on 
>> interfaces), and for local variables.
>> 
>> Many benefits would accrue to us, should we adopt this default:
>> 
>> 1. final fields must be initialized in a constructor and never mutated 
>> again. This makes reasoning about those fields easier.
>> 2. classes that have all their fields final are immutable and hence easier 
>> to reason about: they can be passed between threads, for instance, with no 
>> need to protect from races
>> 3. final method parameters can never be mutated, making them easier to 
>> reason about
>> 4. final local variables can never be mutated, making them easier to reason 
>> about
>> 
>> When final is the rule, non-final is the exception. Another way of saying 
>> that is that when final is the rule, mutability is the exception. That is as 
>> it should be. Mutability is the enemy.
>> 
>> I have turned on a couple IntelliJ settings that make this the default for 
>> me. I encourage you to do the same:
>> 
>> First there are these two "Code style issues" in the Java inspections:
>> 
>> "Field may be 'final'"
>> "Local variable or parameter can be final"
>> 
>> 
>> 
>> Then there is this setting will cause newly-defined variables created via 
>> the "Extract variable" refactoring:
>> 
>> If you select that check box (after selecting those inspections settings 
>> above), it'll declare the newly-introduced variable "final" and it'll 
>> remember the setting the next time you invoke "Extract variable" refactoring
>> 
>> 

Reply via email to