Hi John, the semantics of a lazy final instance field and a lazy final static field are different, likewise the semantics of an instance field and a static field are different too, by example the static fields are initialized under a lock but there is no implicit lock around the instance fields initializations in a constructor.
The concept of "lazy final" is coarsely the same between static and instance fields, but semantics is slightly different, people will get a NPE if they try to use null with an instance field but not if it's a static field because the constant pool does the bookkeeping. Disallowing null for lazy static field goes a step too far in term of design, because it introduce an arbitrary limitation for the shake of having a common semantics. I think it's an overdesign. And there are two other arguments: - as you said, the static lazy final is very more important than the instance one and we want to help users to over use it so if we can not introduce a discrepancy between a static final and a lazy static final, we should do it. - why null is not a valid value for a lazy final instance field ? We can decide to allow null to signal that the instance field is still not initialized despite that the initialisation sequence has been run. Rémi ----- Mail original ----- > De: "John Rose" <john.r.r...@oracle.com> > À: "Maurizio Cimadamore" <maurizio.cimadam...@oracle.com> > Cc: "valhalla-spec-experts" <valhalla-spec-experts@openjdk.java.net> > Envoyé: Samedi 2 Mars 2019 20:37:35 > Objet: Re: lazy statics design notes > On Mar 1, 2019, at 3:47 AM, Maurizio Cimadamore > <maurizio.cimadam...@oracle.com> > wrote: >> >> From a technical perspective I don't think there's any issue. You get condy >> semantics, which, as you say, is well defined w.r.t. cycles and laziness etc. >> >> From a language perspective I see an issue if we expect, as we said, that >> most >> people will just jump in and replace 'static' with 'lazy-static'. That is >> gonna >> have all sorts of behavioral incompatibilities. > > The first time someone gets an error because the value of the lazy-static is > null, > they will say "those idiots", etc. Whereas we want them to think of adding > laziness > as a simple, foolproof way to get certain kinds of performance improvements. > > This is a good point, and may overcome my arguments. It will push the > friction > forward in time, to the place where we add non-static lazies; at that point we > will have a less pleasant choice between transactional memory and reserving > the value I am asking we reserve *now*. > > (BTE, this is a classic example of something that looks great from the VM > looking > upward doesn't look so great from the user model looking downward.) > > So, I want to defend my proposal a little more, not only by saying we'll pay > a cost later if we don't reserve the value now, but also by noting that your > point about "all sorts of behavioral incompatibilities" applies more evenly > than you may think, to both proposals (reserve a value, vs. don't reserve). > > Even if you allow the full range of values, including null, there will be > all sorts of more subtle behavioral incompatibilities just from changing > the order in which statics are initialized, and (what's more) making the > order dynamically data dependent. The bugs that folks will run into > from "going lazy" will be bootstrap ordering bugs, causing null > pointer exceptions (typically) when one initializer needs access to > a non-lazily initialized static in some other class. > > Bootstrap errors happen all the time when there are delicate inter-class > initialization dependencies. Today we see it when static initializers > recurse into themselves via another class. Tomorrow we will see it > whenever there is a mix of lazy and non-lazy initialization. > > So, I don't buy that non-reservation of null is going to especially improve > the user experience. It will remove one moderately sharp edge, leaving > some sharper ones. I'm saying the reserved value is "moderately" sharp, > because it is relatively easy to diagnose, compared with bootstrap ordering > bugs, which are always non-local in nature. > > And, just to repeat another bit: We have already bitten the "no nulls" bullet > with Optional. We are telling users that, for certain constructs, nulls are > out of policy. That too could cause "all sorts of incompatibilities", making > it hard to refactor to use the new feature (Optionals). So it feels like a > defensible move here also. "Lazies are a language supported form of > optionals which automatically change state from empty. You can't put > nulls in them." What's hard about that? Especially if we make reflection > and/or method handle versions which return an actual Optional if the > user wants to do a non-triggering sense of the state. > > Anyway, on balance, I'd still prefer to make lazies like optionals, and > then continue to align them that way when we get to non-static lazies > and (if we go there) use-site lazies. > > I didn't say "if we go there" for non-static lazies because they are so > freaking useful *today*, under the disguise of @Stable. We'll want to > go there. > > HTH > > — John