Data Oriented Programming, Beyond Records
Brian Goetz
brian.goetz at oracle.com
Sun Jan 18 01:00:19 UTC 2026
In reality, the deconstructor is not a method at all.
When we match:
x instanceof R(P, Q)
we first ask `instanceof R`, and if that succeeds, we call the accessors
for the first two components. The accessors are instance methods, but
the deconstructor is not embodied as a method. This is true for
carriers as well as for records.
On 1/17/2026 5:09 PM, forax at univ-mlv.fr wrote:
>
>
> ------------------------------------------------------------------------
>
> *From: *"Viktor Klang" <viktor.klang at oracle.com>
> *To: *"Remi Forax" <forax at univ-mlv.fr>, "Brian Goetz"
> <brian.goetz at oracle.com>
> *Cc: *"amber-spec-experts" <amber-spec-experts at openjdk.java.net>
> *Sent: *Saturday, January 17, 2026 5:00:41 PM
> *Subject: *Re: Data Oriented Programming, Beyond Records
>
> Just a quick note regarding the following, given my experience in
> this area:
>
> On 2026-01-17 11:36, Remi Forax wrote:
>
> A de-constructor becomes an instance method that must return a
> carrier class/carrier interface, a type that has the
> information to be destructured and the structure has to match
> the one defined by the type.
>
>
> Hello Viktor,
> thanks to bring back that point,
>
> This simply *does not work* as a deconstructor cannot be an
> instance-method just like a constructor cannot be an instance
> method: It strictly belongs to the type itself (not the hierarchy) and
>
>
> It can work as you said for a concrete type, but for an abstract type,
> you need to go from the abstract definition to the concrete one,
> if you do not want to re-invent the wheel here, the deconstructor has
> to be an abstract instance method.
>
> For example, with a non-public named implementation
>
> interface Pair<F, S>(F first, S second) {
> public <F,S> Pair<F,S> of(F first, S second) {
> record Impl<F, S>(F first, S second) implements Pair<F, S>{ }
> return new Impl<>(first, second);
> }
> }
>
> inside Pair, there is no concrete field first and second, so you need
> a way to extract them from the implementation.
>
> This can be implemented either using accessors (first() and second())
> but you have a problem if you want your implementation to be mutable
> and synchronized on a lock (because the instance can be changed in
> between the call to first() and the call to second()) or you can have
> one abstract method, the deconstructor.
>
> it doesn't play well with implementing multiple interfaces (name
> clashing), and interacts poorly with overload resolution (instead
> of choosing most-specific, you need to select a specific point in
> the hierarchy to call the method).
>
>
> It depends on the compiler translation, but if you limit yourself to
> one destructor per class (the dual of the canonical constructor), the
> deconstructor can be desugared to one instance method that takes
> nothing and return java.lang.Object, so no name clash and no problem
> of overloading (because overloading is not allowed, you have to use
> '_' at use site).
>
> --
> Cheers,
> √
>
>
> regards,
> Rémi
>
> Viktor Klang
> Software Architect, Java Platform Group
> Oracle
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/amber-spec-experts/attachments/20260117/304d916d/attachment-0001.htm>
More information about the amber-spec-experts
mailing list