An improvement request on records

Tagir Valeev amaembo at gmail.com
Thu Dec 11 16:33:09 UTC 2025


Hello!

Well, as you have reposted this, I assume that you are not against some
discussion on the topic.

The both use-cases mentioned by Kai Hofmann are about caching some
intermediate computation derived from the record fields to improve the
performance of the application (they are not strictly necessary for
correctness).
In his case, such cached values are computed in the constructor, which is
somewhat unusual for (presumably heavy) computation. What if we only use
the methods that never access these cached values? In this case, the
computation will be just a waste of CPU time.
Usually, people perform heavy computations on demand, deferring the
computation until it's actually necessary (e.g., String.hash field). Now,
we have a perfect construct for this: LazyConstant. So I may imagine
enhanced records with a new feature:

- private final fields in records are allowed only if their type is
LazyConstant
- such fields must have an initializer like LazyConstant.of(() -> lambda)
- the initializer is guaranteed to see the record components. So we cannot
use such fields in constructor prolog (or in compact constructor), before
all the components are assigned
- it's assumed (though not statically checked) that such fields depend on
record components only. They are always transient and not initialized after
deserialization.

We may also devise some kind of syntactic sugar for LazyConstant fields
(not only in records!). E.g. declare them like `private lazy T cached =
initializer;` instead of `private final LazyConstant<T> cached =
LazyConstant.of(() -> initializer);`. Having an ability to declare such
fields will simplify the record specification: we can simply allow fields
with 'lazy' modifier (which always implies 'final') without saying anything
about type.

I'm not saying that it's something that we should do right now, especially
taking into account that LazyConstants are still in preview. But probably
something useful here could be done in the future.

With best regards,
Tagir Valeev

On Thu, Dec 11, 2025 at 5:01 PM Brian Goetz <brian.goetz at oracle.com> wrote:

> The below was received on amber-spec-comments.
>
> The author makes a renewed plea for final, non-component fields in
> records.
>
> This point was discussed extensively during the design of records, so I
> won't recapitulate the discussion here.
>
>
> -------- Forwarded Message --------
> Subject: An improvement request on records
> Date: Thu, 11 Dec 2025 15:27:28 +0100
> From: Kai Hofmann <java at kai-hofmann.de> <java at kai-hofmann.de>
> To: amber-spec-comments at openjdk.org
>
> To whom it may concern,
>
> I am working here since some years on my OpenSource projects, and until
> now I had never a reason to made comments on Java - but now I feel I have
> to raise my voice on records:
>
>
> Since some years I developed a library of DDD valueObjects both as normal
> Java objects and also in a parallel branch as records. At the moment you
> can find this work here:
>
> https://github.com/PowerStat/Validation
>
> But I plan to rename this project, because in the meantime the project
> name is no longer a good choice - maybe it will name something like
> ValueObjectLibrary - you will find it under my github repos.
>
>
> So from my experiences I can say it is a correct design decision to not
> have instance fields within records.
>
> But in my opinion this thought is to simple, because private "final"
> instance fields should be possible and will be useful and could safe
> duplicated code as well as runtime!
>
> So the point is that final instance fields have to be initialized within
> the constructor and will be unchangeable after a record has been
> constructed - so they are harmless!
>
> As an example I have implemented a MACAddress class/record that represents
> a hardware mac address.
>
> Within the normal class implementation I split the mac address into it's
> parts only once within the construtor, later on I have multiple methods
> that work on this split parts.
>
> But within a record this is not possible so I have to do the split within
> every method where I need it - thats waste of code and runtime!
>
> Another example is my implementation of the ISBN13 - see
> https://en.wikipedia.org/wiki/ISBN
>
> These numbers could come with 2 different formats: with or without
> separator chars in it - both formats are equal.
>
> So in my class implementation I would do a normalization (without
> separators) and store this one internally.
>
> Within a record this normalization in the construtor is not possible,
> because I could not have instance fields nor could I change the records
> parameter within the constructor because its already fixed :(
>
> So ISBN13 could not be implemented as a record!
>
> I vote for extending the record specification to have private "final"
> instances within it and maybe to allow to manipulate the construction
> parameters within the constructor.
>
> Would be nice to hear from you about this.
>
>
> Greetings and have a nice Christmas and a Happy New Year.
>
>
> PowerStat (Kai Hofmann)
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/amber-spec-experts/attachments/20251211/f1c0b57d/attachment-0001.htm>


More information about the amber-spec-experts mailing list