Feature Request -- Enumerate the RecordComponents of a record

David Alayachew davidalayachew at gmail.com
Mon Dec 1 20:15:54 UTC 2025


Thanks for the response @Attila Kelemen <attila.kelemen85 at gmail.com>.

Yes, I am definitely not married to the concept of using an enum or an
inner class. There are clear flaws with it, and I only use it to explain
what I really want.

Really, all I want is to be able to enumerate the components of a record
and also get exhaustiveness checking.

As for your implementation suggestion, no real comments. As long as it
works, I am fine with any implementation.


On Mon, Dec 1, 2025, 1:10 PM Attila Kelemen <attila.kelemen85 at gmail.com>
wrote:

> Hi,
>
> My concern with the actual proposal (not with the problem it is trying to
> solve) is that it doesn't generalize well. That is, imagine if function
> types get added to the language with support to query the parameters, etc.
> of the underlying function. Then immediately this change becomes a useless
> (in fact, harmful) noise.
>
> So, let me give a counter proposal (even though I'm quite certain it will
> not be added anytime soon given all the important stuff in the queue):
>
> Allow the following construct:
>
> ```
> RecordComponentAccessor accessor = MyRecord::myComponent;
> ```
>
> where the `RecordComponentAccessor` could look like it (of course, doesn't
> have to be an interface):
>
> ```
> interface RecordComponentAccessor<R, V> {
>   Type recordType();
>   Class<? extends R> recordRawType();
>
>   String componentName();
>
>   Type componentType();
>   Class<?> componentRawType();
>
>   MethodHandle getter();
>
>   default V getValue(R record) {
>      // TODO: Deal with `throws Throwable`
>     return getter().invoke(record);
>   }
> }
> ```
>
> The benefit of this is that, if function types ever become a thing, then
> of course this can be retrofitted to implement (or extend) the function
> type `(R) -> V` (or whatever notation it would have), which would likely
> have more generic methods like `List<Class<?>> parameterRawTypes()`, etc.
>
> In my opinion, this is not harder to implement than the original proposal,
> and more future proof. And if it is only implemented for records, then no
> massive changes to the JVM needed (unlike with the introduction of a full
> blown function type).
>
> Attila
>
> David Alayachew <davidalayachew at gmail.com> ezt írta (időpont: 2025. nov.
> 30., V, 22:51):
>
>> Hello @amber-dev <amber-dev at openjdk.org>,
>>
>> (this is a follow-up from the previous thread --
>> https://mail.openjdk.org/pipermail/amber-dev/2025-November/009472.html)
>>
>> Since records are *transparent* carriers of data, then that means that
>> all of the record components are known at compile time and visible to all
>> consumers who can reach the record itself.
>>
>> Right now, the only way to reach these record components is by drilling
>> down via j.l.Class ---> j.l.r.RecordComponent. And even then, you are
>> forced into doing String comparison against what you *expect* the record
>> component to be named. That means that you will get a runtime error, not a
>> compile time error, if a record component changes names.
>>
>> I propose that we enumerate the Record Components of a record.
>>
>> My naive way of accomplishing this would be to literally provide each
>> record with its own inner enum, each value corresponding to the respective
>> record component on a record.
>>
>> Consider the following record.
>>
>> record User(String firstName, String lastName, int age) {}
>>
>> I ask that record get access to its own inner enum (let's call it
>> VALUES), that can be referenced. Like this.
>>
>> record User(String firstName, String lastName, int age)
>> {
>>     enum Values {
>>         firstName,
>>         lastName,
>>         age,
>>         ;
>>         public final java.lang.reflect.RecordComponent recordComponent =
>>                 Arrays
>>                     .stream(User.class.getRecordComponents())
>>                     .filter(rc -> rc.getName().equals(this.name()))
>>                     .findAny()
>>                     .orElseThrow()
>>                     ;
>>     }
>> }
>>
>> This is better than the current situation for all sorts of reasons.
>>
>>    1. Currently, if I want a RecordComponent, I must make a
>>    String-comparison. I lose compile time safety of checking if my hard-coded
>>    string no longer matches because someone changed the record.
>>    2. I now get exhaustiveness checking, which really should have been
>>    there from the beginning.
>>
>> And of course, I am not tied to the idea of using an enum or an inner
>> class. My real goal is to be able to enumerate over the components of a
>> record. Not even necessarily over the j.l.r.RecordComponents of a record.
>> Whatever form that takes is fine with me.
>>
>> But not being able to enumerate over a records components (obviously, in
>> a type-safe, non-*stringly*-typed way) is making records less powerful
>> for seemingly no reason. The contract and spec enables it, it's just not
>> being utilized.
>>
>> Thank you for your time and consideration.
>> David Alayachew
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/amber-dev/attachments/20251201/408efe54/attachment.htm>


More information about the amber-dev mailing list