crazy idea: weaken the effectively final restriction

Attila Szegedi szegedia at
Wed Oct 6 19:45:32 UTC 2021

My personal code style is so far on the other end of this spectrum that I wouldn’t ever want this feature. I notoriously single-assign all my local variables to the point of spelling out “final var” just to make sure the compiler catches me if I deviate from it. Very rarely I’ll settle for reassignment (mostly in a loop that accumulates a value. I could do away with most of those too if I could tell the Java compiler to transform tail recursive methods into loops.) Ultimately, I’d never reassign a method parameter. Yes, I declare those as “final” too; my Java code is full of “final” keywords but what can I do when immutability ain’t the default…

I’m not trying to look down from a high horse and champion this as the ultimate style everyone should adopt, but it works for me. Gives me a peace of mind when my variables don’t vary much. It sure is easier for me to read and reason about my code when I revisit it after some time if I don’t have to worry about a variable changing further down the method once I understood the first and only expression that computes its value.


> On 2021. Oct 6., at 19:56, John Rose <john.r.rose at> wrote:
> On Oct 5, 2021, at 2:55 PM, mark.yagnatinsky at<mailto:mark.yagnatinsky at> wrote:
> Runnable f(String s) {
>               s = normalize(s);
>               return () -> println(s); // no can do: s is not effectively final
> }
> However, this seems a bit silly because although s is not final throughout the entire method, it's final where it actually matters.
> As the experts have said, it is by design that the
> finality can be applied to the declaration *regardless
> of use*.  This yields a language that is easier to
> reason about.  (Yes, we did spend a lot of complexity
> budget elsewhere on lambdas as poly expressions,
> which nobody understands.  To excuse that, that
> bit of magic happens during overload resolution,
> which nobody understood anyway.)
> Namely, it is final from the point of capture to the end of the method, and that's the only condition we need to avoid those annoying questions.
> I have wanted this feature from time to time, but
> here’s another indication that it won’t pull its
> weight (of complexity):  You can easily, even
> automatically (with IDE help) work around the
> limitation, simply by rebinding the variable
> you intend to capture.  That’s the cost of
> using the simpler (more reusable) semantics
> of effectively final variables:  Sometimes
> you need a second binding if the system
> cannot read your mind about how you
> are using the first binding.
> Runnable f(String s) {
>               s = normalize(s);
>               var s1 = s;
>               return () -> println(s1); // fixed it for you!
> }
> Something’s gotta give:  Either more mind-reading
> rules for bindings, or more bindings.  This is arguably
> the more Java-like approach.
> Note also that the worst kind of mind-reading can
> happen when a maintainer reads your code.  In that
> case, the maintainer will surely prefer the more
> transparent (though ceremonious) formulation
> with s1.
> Full disclosure:  As a coder I grumble every time
> I have to write an “s1”.  But as a reader of code I
> don’t mind them so much.

More information about the jdk-dev mailing list