+1 to auto-enforcement (if possible) post-consensus On Tue, Jun 18, 2019 at 8:33 AM Murtuza Boxwala <mboxw...@pivotal.io> wrote:
> 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 > >> > >> > >