From rob.ross at gmail.com Sat Nov 1 02:43:08 2025 From: rob.ross at gmail.com (Rob Ross) Date: Fri, 31 Oct 2025 19:43:08 -0700 Subject: Ad hoc type restriction In-Reply-To: References: <651bcb1a-3dba-48c8-b615-740034760d88@oracle.com> <36edf5e8-791e-4d31-8e7d-05cea3eabd22@oracle.com> <_hpWIJCY4KKm-omhziKAtP-HzavBj0EWmR2PVZa236HpRJNKeovu8Ni1PtaVMTVk1-Tawmxtiz7gGQx_b70MmIXJ0KCEBRMwtdWnxx8Y6g8=@proton.me> Message-ID: On Fri, Oct 31, 2025 at 8:10?AM Archie Cobbs wrote: > On Thu, Oct 30, 2025 at 9:38?PM Rob Ross wrote: > >> Contracts, `runtime` and `compile time`... >> > > All good thoughts. > > 1. Strongly-typed languages like Java are favored for complex > programming tasks because of the rich tools they provide to programmers > allowing one to prove to oneself that the code's behavior will be correct. > This is Java in a nutshell! > 2. In general, such tools will operate at *both* compile/build time > and runtime - and they should do so in a coherent way. > > The observation I'm trying to make in this thread is: Java gives its own > tools the ability to operate seamlessly across both domains (compile-time > and runtime) but it makes it difficult for the programmer to add their own > tools that operate seamlessly across both domains. > > -Archie > > I wasn't trying to suggest it was a either/or implementation. Just pointing out that *some* kinds of preconditions could be completely determined at compile time, and if so, there may not even be a need for any of those checks to be included in generated bytecode. Of course, most checks will require code to execute at runtime. And so the ability to ignore them (or some of them) at runtime would be an important feature in this system. Checks facilitate fast-fail program design, which makes code easier to debug. Checks also impose a runtime penalty that may not be warranted in mature, well-tested code. That's why I love asserts. They give me the best of both worlds. During development, ideally you would program by contract with every function that takes parameters and returns data. This is the ultimate safety net. So a system that makes this easy to implement would be a huge productivity gain. And the ability to turn them off when they are not needed is a (potential) performance gain. I see three use case categories regarding contract programming. 1. Internal, private, "black box" code 2. API code 3. Performant "expert" libraries 1. During development of your private implementation code, programming by contract has all the benefits discussed in this thread. But since you own this code, you are in the position to know when it is stable and mature and calls your internal methods with the correct arguments. You can leave the checks on during development and on your dev/test systems. But you have the option to improve performance in production by turning these checks off. 2. API code - since you can't control what foreign code is going to pass you, these checks will probably need to remain enabled even in production. 3. Expert libraries - think of a C graphics library where speed is critical. There is likely no error checking at all. You're on the "honor system" to pass correct data. However, you could still benefit from enabled checking in dev and test, still catching bugs quicker, and still optimized for speed in production. That's why I love the asserts model. My mental picture of them is as a safety net at a construction site. You put up a net around areas where people might fall to prevent them from getting hurt. But when the building is completed, you remove the safety net. The beauty of software as a "virtual world" is that you can set up and tear down your virtual safety net with a simple compiler or jvm option flag. - Rob -------------- next part -------------- An HTML attachment was scrubbed... URL: From mikhail.vorobev at jetbrains.com Mon Nov 10 15:51:22 2025 From: mikhail.vorobev at jetbrains.com (Mikhail Vorobev) Date: Mon, 10 Nov 2025 16:51:22 +0100 Subject: Feedback on LazyConstant (previously StableValue) Message-ID: Hello Amber Team, I write to provide a data point from the Kotlin Evolution Team on the design of LazyConstant (previously StableValue). In Kotlin, there is a `lateinit var` declaration for a variable that is in an uninitialized state until it is assigned later during execution, after that it behaves like a normal variable. In practice, people tend to use such declarations primarily for variables with stable semantics, e.g. for injected dependencies or Android View bindings: class Application { @Inject lateinit var service: Service } class MyActivity : AppCompatActivity() { lateinit var view: ImageView override fun onCreate(...) { view = findViewById(R.id.image) } } These variables are intended to be initialized at most once and never change after that. To cater to such use cases, we considered introducing `lateinit val` declaration in some form (possibly just as a delegate, similar to how lazy is implemented now in Kotlin). StableValue was a perfect fit for the implementation of `lateinit val`. On the other hand, LazyConstant could not be used to express desired semantics (without hacks) due to its limited API: it does not allow setting the value directly after construction. >From our point of view, the current LazyConstant API, in contrast to StableValue, does not cover a considerable part of use cases for variables with stable semantics where they are initialized from values available later and there is no sensible initializer function that could be provided beforehand. Best Regards, Mikhail Vorobev, Kotlin Evolution Team -------------- next part -------------- An HTML attachment was scrubbed... URL: From maurizio.cimadamore at oracle.com Mon Nov 10 16:45:55 2025 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Mon, 10 Nov 2025 16:45:55 +0000 Subject: Feedback on LazyConstant (previously StableValue) In-Reply-To: References: Message-ID: <2f18ec55-6aa0-4a3b-b4c7-26b3ab6ad2e4@oracle.com> Hi Mikhail, you are correct LazyConstant aims at the 80% use case, which is more similar to Kotlin's "lazy" keyword. As stated here: https://mail.openjdk.org/pipermail/leyden-dev/2025-September/002712.html > That said, the quest for a more fundamental building block is not over: we now have a clearer idea on how to expose "stable" access to regular fields/array elements, using a _new_ var handle access mode. Initial experiments look indeed promising: such an approach doesn't require the allocation of intermediate abstractions, and allows clients to decide if they want to pay for synchronization or not. In other words, something else (lower level) will appear at some point in the future to "complete" the API. I believe the VarHandle-based solution we're exploring should be an even better translation target for Kotlin, as with the outlined strategy you'd now be in control of whether you need non-plain access, synchronization, etc. Maurizio On 10/11/2025 15:51, Mikhail Vorobev wrote: > > Hello Amber Team, > > I write to provide a data point from the Kotlin Evolution Team on the > design of LazyConstant (previously StableValue). In Kotlin, there is a > `lateinit var` declaration for a variable that is in an uninitialized > state until it is assigned later during execution, after that it > behaves like a normal variable. In practice, people tend to use such > declarations primarily for variables with stable semantics, e.g. for > injected dependencies or Android View bindings: > > > ????class Application { > > ????????@Inject lateinit var service: Service > > ????} > > > ????class MyActivity : AppCompatActivity() { > > ????????lateinit var view: ImageView > > ????????override fun onCreate(...) { > > ????????????view = findViewById(R.id.image) > > ????????} > > ????} > > > These variables are intended to be initialized at most once and never > change after that. To cater to such use cases, we considered > introducing `lateinit val` declaration in some form (possibly just as > a delegate, similar to how lazy is implemented now in Kotlin). > > > StableValue was a perfect fit for the implementation of `lateinit > val`. On the other hand, LazyConstant could not be used to express > desired semantics (without hacks) due to its limited API: it does not > allow setting the value directly after construction. > > > From our point of view, the current LazyConstant API, in contrast to > StableValue, does not cover a considerable part of use cases for > variables with stable semantics where they are initialized from values > available later and there is no sensible initializer function that > could be provided beforehand. > > Best Regards, Mikhail Vorobev, Kotlin Evolution Team > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From davidalayachew at gmail.com Tue Nov 25 12:14:48 2025 From: davidalayachew at gmail.com (David Alayachew) Date: Tue, 25 Nov 2025 07:14:48 -0500 Subject: My experience with IO.print() and IO.println() Message-ID: Hello @amber-dev , I finally had the chance to tutor a couple kids, this time, using the new IO class, and I wanted to post my experience about them thus far, in case it would be useful. If I had to quantify and compare the friction and trip factor relative to System.out.println(), it's a fairly noticeable difference. For example, there are a certain "type" of students that have a brain that REFUSES to accept new info until they understand ALL details of what's in front of them. What is System? What is out? Does the dot have meaning? Why are there 2? What are the parentheses? The more you expose them to, the more they dig. And while digging seems good at first, they tend to be mental pack hoarders, carrying around all of these details and cross-referencing them against any new information that their brain can now finally accept. Thus, they tend to get overburdened quickly, and that's assuming that your explanation holds up to scrutiny. Lol, they're like little detectives. I've had a long list of these type of students for years, and they are usually the ones bothered by System.out.println() the most out of any of the students. Well, explaining IO.println() ended up being a much smoother experience. For starters, the phrase IO is something most students have "heard of" and are vaguely familiar with, so to put "face to name" is something they appreciate. That input/output explanation tends to go a long way for these kids. A lot easier to explain compared to System, especially for the students who have an IDE with autocomplete. Furthermore, communicating that IO is just a bucket for a small handful of simple input/output methods works well because, the size of the class means that the type of students that like to dig get to the bottom of the hole very quickly, and thus, aren't held up for nearly as long. Back when this feature was in preview, I had my own wants to add to the list of potential methods to IO. Looking at it now, it's clear that its minimality is a strength. Then there is the obvious benefit of not having to use Scanner anymore. The results were exactly as expected here. Nothing to report. Deferring to things like Integer.parseInt proved to be a mild obstacle, and one that was easily overcome. Sure, it was an obstacle we previously didn't have, but the tradeoff is a good one imo. Finally, I'd like to praise the choice to make IO.println() a static method. I'm sure that the decision-making was obvious, but I cannot state enough how much easier it is to teach students the foundational concepts when working purely with static, stateless, utility/helper functions. And most importantly, about NOT BEING FORCED TO TEACH THEM CLASS INSTANCES/IDENTITY. Easily the biggest benefit of having these be static methods. All in all, a great success. Thanks again Project Amber team for moving a mountain out of the way for us! Thank you for your time and attention. David Alayachew Side note -- I know it might seem flippant of me to group students into "types", but after 13 years of tutoring, I've found it to be an effective strategy for picking a choice when all else is equal. Not all strategies work for all students. And while you can pick the least bad, general solution, you do tend to get forced into specializing your teaching for each student, case-by-case. That goes beyond programming, but for education period. -------------- next part -------------- An HTML attachment was scrubbed... URL: From davidalayachew at gmail.com Sat Nov 29 19:44:56 2025 From: davidalayachew at gmail.com (David Alayachew) Date: Sat, 29 Nov 2025 14:44:56 -0500 Subject: Reflection on records Message-ID: Hello @amber-dev , I asked this on core-libs-dev already, but I figured I should ask here too. Let's say I have some record User(String firstName, String lastName) {}. Is there any possible way for me to do the following? java.lang.reflect.RecordComponent firstName = foo(User::firstName); I'll even accept this. java.lang.reflect.Method lastName = foo(User::lastName); Thank you for your time and consideration. David Alayachew -------------- next part -------------- An HTML attachment was scrubbed... URL: From davidalayachew at gmail.com Sat Nov 29 19:49:36 2025 From: davidalayachew at gmail.com (David Alayachew) Date: Sat, 29 Nov 2025 14:49:36 -0500 Subject: Reflection on records In-Reply-To: References: Message-ID: And by all means, add more parameters to foo if you want. For example, if a User.class helps, please do so! I just don't want to do anything like this. foo("firstName"); That's stringly typed, and undesirable for my use case. -------------- next part -------------- An HTML attachment was scrubbed... URL: From archie.cobbs at gmail.com Sat Nov 29 22:08:34 2025 From: archie.cobbs at gmail.com (Archie Cobbs) Date: Sat, 29 Nov 2025 16:08:34 -0600 Subject: Ad hoc type restriction In-Reply-To: References: <651bcb1a-3dba-48c8-b615-740034760d88@oracle.com> <36edf5e8-791e-4d31-8e7d-05cea3eabd22@oracle.com> Message-ID: On Wed, Oct 15, 2025 at 7:10?PM Archie Cobbs wrote: > On Wed, Oct 15, 2025 at 11:34?AM Manu Sridharan > wrote: > >> This is all mostly possible via the Checker Framework and similar >> approaches. >> > > In the spirit of due diligence, I am attempting to implement something > like "WHAT I WANT" using the checker framework > Just a little follow-up on this "due diligence" project... (a summary of the idea is here ). I'm declaring defeat for now due to an insufficient product of ability?time. A few debrief notes... 1. I was unable to get basic questions answered about the checker framework, for example, how to handle dynamically detected annotation types. Probably because the discussion group is broken . Unfortunately I don't have time to figure that part out on my own. 2. Thanks to the ClassFile API, the runtime checking component of this idea was fairly fun & easy to prototype (working example here ). 3. There are still a few holes in the RuntimeVisibleTypeAnnotations class file attribute representation of uses of type annotations in Java source, e.g., JDK-8371735 and JDK-8371733 . These make me wonder whether anyone is actually using these attributes much in the real world. So for now, this dream of simple, custom type restrictions is still, um, available :) -Archie -- Archie L. Cobbs -------------- next part -------------- An HTML attachment was scrubbed... URL: From attila.kelemen85 at gmail.com Sun Nov 30 19:15:58 2025 From: attila.kelemen85 at gmail.com (Attila Kelemen) Date: Sun, 30 Nov 2025 20:15:58 +0100 Subject: Reflection on records In-Reply-To: References: Message-ID: I'm pretty sure there is no such thing, because that essentially implies the existence of some kind of method literal (well, it would not be strictly necessary, but the JLS would feel strange without it), and there is no such thing (though it would be awesome, if there was). Also, note that if this was a thing, then your case is just a very special case, and you would want more (I would for sure). That is, in that case, I would also want type safety. So, something like MethodReference<(MyRecord) -> String> (which of course would require function types in Java). When I needed this, luckily I could restrain my need to interface methods (as opposed to your record getters) where I could create a `Proxy` and see which method gets called (nasty hack, has its downsides, but felt like the safest to me). Attila David Alayachew ezt ?rta (id?pont: 2025. nov. 29., Szo, 20:50): > And by all means, add more parameters to foo if you want. For example, if > a User.class helps, please do so! > > I just don't want to do anything like this. > > foo("firstName"); > > That's stringly typed, and undesirable for my use case. > -------------- next part -------------- An HTML attachment was scrubbed... URL: From davidalayachew at gmail.com Sun Nov 30 19:41:23 2025 From: davidalayachew at gmail.com (David Alayachew) Date: Sun, 30 Nov 2025 14:41:23 -0500 Subject: Reflection on records In-Reply-To: References: Message-ID: Thanks for the response Attila. Let me try and loosen the constraints then -- is there any way for me to get a RecordComponent corresponding to firstName without needing to do String comparison? At the end of the day, that's all that I really need. As is now, the only way I can see to get a RecordComponent is to drill down from j.l.Class --> j.l.r.RecordComponent, then do String comparison against a provided String to get the record component that I want. That is unsafe and stringly typed, so, very much undesirable. After all, if I change my record to say first instead of firstName, I want a compiler error. But doing it that way, I won't -- I'll get a runtime error. So that's what I really want -- a type-safe way to isolate a record component from a record, without forcing my users to have to provide a String corresponding to the record component name. On Sun, Nov 30, 2025 at 2:16?PM Attila Kelemen wrote: > I'm pretty sure there is no such thing, because that essentially implies > the existence of some kind of method literal (well, it would not be > strictly necessary, but the JLS would feel strange without it), and there > is no such thing (though it would be awesome, if there was). > > Also, note that if this was a thing, then your case is just a very special > case, and you would want more (I would for sure). That is, in that case, I > would also want type safety. So, something like MethodReference<(MyRecord) > -> String> (which of course would require function types in Java). > > When I needed this, luckily I could restrain my need to interface methods > (as opposed to your record getters) where I could create a `Proxy` and see > which method gets called (nasty hack, has its downsides, but felt like the > safest to me). > > Attila > > David Alayachew ezt ?rta (id?pont: 2025. nov. > 29., Szo, 20:50): > >> And by all means, add more parameters to foo if you want. For example, if >> a User.class helps, please do so! >> >> I just don't want to do anything like this. >> >> foo("firstName"); >> >> That's stringly typed, and undesirable for my use case. >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: From attila.kelemen85 at gmail.com Sun Nov 30 19:51:01 2025 From: attila.kelemen85 at gmail.com (Attila Kelemen) Date: Sun, 30 Nov 2025 20:51:01 +0100 Subject: Reflection on records In-Reply-To: References: Message-ID: I think that is impossible. What I did when I needed something similar is that I used an interface instead of a record and built utilities around it, because in that case you can imitate what you want. That is, consider that you have `interface User { String firstName(); String lastName() }`. In this case, you could have methods taking a `Function` and then you can create an instance of `User` via `Proxy.newProxyInstance` in which you record which method was called, and pass the proxy instance to the `Function`. Assuming that someone passed `User::firstName` for the `Function`, you can detect which method was passed. The drawbacks are obvious, but it is better than passing strings in my opinion. David Alayachew ezt ?rta (id?pont: 2025. nov. 30., V, 20:41): > Thanks for the response Attila. > > Let me try and loosen the constraints then -- is there any way for me to > get a RecordComponent corresponding to firstName without needing to do > String comparison? > > At the end of the day, that's all that I really need. > > As is now, the only way I can see to get a RecordComponent is to drill > down from j.l.Class --> j.l.r.RecordComponent, then do String comparison > against a provided String to get the record component that I want. That is > unsafe and stringly typed, so, very much undesirable. After all, if I > change my record to say first instead of firstName, I want a compiler > error. But doing it that way, I won't -- I'll get a runtime error. > > So that's what I really want -- a type-safe way to isolate a record > component from a record, without forcing my users to have to provide a > String corresponding to the record component name. > > On Sun, Nov 30, 2025 at 2:16?PM Attila Kelemen > wrote: > >> I'm pretty sure there is no such thing, because that essentially implies >> the existence of some kind of method literal (well, it would not be >> strictly necessary, but the JLS would feel strange without it), and there >> is no such thing (though it would be awesome, if there was). >> >> Also, note that if this was a thing, then your case is just a very >> special case, and you would want more (I would for sure). That is, in that >> case, I would also want type safety. So, something like >> MethodReference<(MyRecord) -> String> (which of course would require >> function types in Java). >> >> When I needed this, luckily I could restrain my need to interface methods >> (as opposed to your record getters) where I could create a `Proxy` and see >> which method gets called (nasty hack, has its downsides, but felt like the >> safest to me). >> >> Attila >> >> David Alayachew ezt ?rta (id?pont: 2025. nov. >> 29., Szo, 20:50): >> >>> And by all means, add more parameters to foo if you want. For example, >>> if a User.class helps, please do so! >>> >>> I just don't want to do anything like this. >>> >>> foo("firstName"); >>> >>> That's stringly typed, and undesirable for my use case. >>> >> -------------- next part -------------- An HTML attachment was scrubbed... URL: From attila.kelemen85 at gmail.com Sun Nov 30 19:56:49 2025 From: attila.kelemen85 at gmail.com (Attila Kelemen) Date: Sun, 30 Nov 2025 20:56:49 +0100 Subject: Reflection on records In-Reply-To: References: Message-ID: I guess, if your record type is fixed, then you can have a dummy instance of that record with all fields being different (hopefully, no 3 boolean components :)), and then you can do the same hack as with the interface + proxy combo. Attila Kelemen ezt ?rta (id?pont: 2025. nov. 30., V, 20:51): > I think that is impossible. What I did when I needed something similar is > that I used an interface instead of a record and built utilities around it, > because in that case you can imitate what you want. > > That is, consider that you have `interface User { String firstName(); > String lastName() }`. In this case, you could have methods taking a > `Function` and then you can create an instance of `User` via > `Proxy.newProxyInstance` in which you record which method was called, and > pass the proxy instance to the `Function`. Assuming that someone passed > `User::firstName` for the `Function`, you can detect which method was > passed. The drawbacks are obvious, but it is better than passing strings in > my opinion. > > David Alayachew ezt ?rta (id?pont: 2025. nov. > 30., V, 20:41): > >> Thanks for the response Attila. >> >> Let me try and loosen the constraints then -- is there any way for me to >> get a RecordComponent corresponding to firstName without needing to do >> String comparison? >> >> At the end of the day, that's all that I really need. >> >> As is now, the only way I can see to get a RecordComponent is to drill >> down from j.l.Class --> j.l.r.RecordComponent, then do String comparison >> against a provided String to get the record component that I want. That is >> unsafe and stringly typed, so, very much undesirable. After all, if I >> change my record to say first instead of firstName, I want a compiler >> error. But doing it that way, I won't -- I'll get a runtime error. >> >> So that's what I really want -- a type-safe way to isolate a record >> component from a record, without forcing my users to have to provide a >> String corresponding to the record component name. >> >> On Sun, Nov 30, 2025 at 2:16?PM Attila Kelemen < >> attila.kelemen85 at gmail.com> wrote: >> >>> I'm pretty sure there is no such thing, because that essentially implies >>> the existence of some kind of method literal (well, it would not be >>> strictly necessary, but the JLS would feel strange without it), and there >>> is no such thing (though it would be awesome, if there was). >>> >>> Also, note that if this was a thing, then your case is just a very >>> special case, and you would want more (I would for sure). That is, in that >>> case, I would also want type safety. So, something like >>> MethodReference<(MyRecord) -> String> (which of course would require >>> function types in Java). >>> >>> When I needed this, luckily I could restrain my need to interface >>> methods (as opposed to your record getters) where I could create a `Proxy` >>> and see which method gets called (nasty hack, has its downsides, but felt >>> like the safest to me). >>> >>> Attila >>> >>> David Alayachew ezt ?rta (id?pont: 2025. >>> nov. 29., Szo, 20:50): >>> >>>> And by all means, add more parameters to foo if you want. For example, >>>> if a User.class helps, please do so! >>>> >>>> I just don't want to do anything like this. >>>> >>>> foo("firstName"); >>>> >>>> That's stringly typed, and undesirable for my use case. >>>> >>> -------------- next part -------------- An HTML attachment was scrubbed... URL: From burnytc at gmail.com Sun Nov 30 20:04:15 2025 From: burnytc at gmail.com (Kirill Semyonkin) Date: Sun, 30 Nov 2025 23:04:15 +0300 Subject: Reflection on records In-Reply-To: References: Message-ID: Hello David, I've seen some people (ab)use Serializable and SerializedLambda to get names of the class and the method, with numerous examples like https://stackoverflow.com/a/53397378/16208077. From there you can traverse usual reflection with those strings to get the exact RecordComponent or some other reflection object. But those strings come from users doing method references, so you will get the behavior that you wanted, at least to some extent. Although it slightly feels like an XY problem. - Kirill Semyonkin ??, 30 ????. 2025??. ? 22:57, Attila Kelemen : > I guess, if your record type is fixed, then you can have a dummy instance > of that record with all fields being different (hopefully, no 3 boolean > components :)), and then you can do the same hack as with the interface + > proxy combo. > > Attila Kelemen ezt ?rta (id?pont: 2025. nov. > 30., V, 20:51): > >> I think that is impossible. What I did when I needed something similar is >> that I used an interface instead of a record and built utilities around it, >> because in that case you can imitate what you want. >> >> That is, consider that you have `interface User { String firstName(); >> String lastName() }`. In this case, you could have methods taking a >> `Function` and then you can create an instance of `User` via >> `Proxy.newProxyInstance` in which you record which method was called, and >> pass the proxy instance to the `Function`. Assuming that someone passed >> `User::firstName` for the `Function`, you can detect which method was >> passed. The drawbacks are obvious, but it is better than passing strings in >> my opinion. >> >> David Alayachew ezt ?rta (id?pont: 2025. nov. >> 30., V, 20:41): >> >>> Thanks for the response Attila. >>> >>> Let me try and loosen the constraints then -- is there any way for me to >>> get a RecordComponent corresponding to firstName without needing to do >>> String comparison? >>> >>> At the end of the day, that's all that I really need. >>> >>> As is now, the only way I can see to get a RecordComponent is to drill >>> down from j.l.Class --> j.l.r.RecordComponent, then do String comparison >>> against a provided String to get the record component that I want. That is >>> unsafe and stringly typed, so, very much undesirable. After all, if I >>> change my record to say first instead of firstName, I want a compiler >>> error. But doing it that way, I won't -- I'll get a runtime error. >>> >>> So that's what I really want -- a type-safe way to isolate a record >>> component from a record, without forcing my users to have to provide a >>> String corresponding to the record component name. >>> >>> On Sun, Nov 30, 2025 at 2:16?PM Attila Kelemen < >>> attila.kelemen85 at gmail.com> wrote: >>> >>>> I'm pretty sure there is no such thing, because that essentially >>>> implies the existence of some kind of method literal (well, it would not be >>>> strictly necessary, but the JLS would feel strange without it), and there >>>> is no such thing (though it would be awesome, if there was). >>>> >>>> Also, note that if this was a thing, then your case is just a very >>>> special case, and you would want more (I would for sure). That is, in that >>>> case, I would also want type safety. So, something like >>>> MethodReference<(MyRecord) -> String> (which of course would require >>>> function types in Java). >>>> >>>> When I needed this, luckily I could restrain my need to interface >>>> methods (as opposed to your record getters) where I could create a `Proxy` >>>> and see which method gets called (nasty hack, has its downsides, but felt >>>> like the safest to me). >>>> >>>> Attila >>>> >>>> David Alayachew ezt ?rta (id?pont: 2025. >>>> nov. 29., Szo, 20:50): >>>> >>>>> And by all means, add more parameters to foo if you want. For example, >>>>> if a User.class helps, please do so! >>>>> >>>>> I just don't want to do anything like this. >>>>> >>>>> foo("firstName"); >>>>> >>>>> That's stringly typed, and undesirable for my use case. >>>>> >>>> -------------- next part -------------- An HTML attachment was scrubbed... URL: From davidalayachew at gmail.com Sun Nov 30 20:37:38 2025 From: davidalayachew at gmail.com (David Alayachew) Date: Sun, 30 Nov 2025 15:37:38 -0500 Subject: Reflection on records In-Reply-To: References: Message-ID: Thanks everyone for the context. The answers I am getting are very helpful. I do see a comment about XY problem, so here is the full context of my problem. Unlike normal classes, record are transparent data carriers. Which make them useful for simple DTO's and serialization. Specifically, I wanted to create a De/serialization format for a CSV file. Let's say I have record User(String firstName, String lastName, ComplexObject complexColumn) {}, and each RecordComponent corrsponds to a column of my CSV, while each instance of User corresponds to a single row. Let's also assume that firstName and lastName are computationally cheap to deserialize, but complexColumn is expensive (complex but necessary regex). Well, I want to create a CSV De/Serialization tool that allows me to not only deserialize the object in full, but also deserialize only the specific component I want. In this case, if all I care about is firstName and lastName, then why should I pay the price of also deserializing complexColumn, which I won't use at all? Hence why I requested these various things in the thread -- such as the ability to reference RecordComponents, or why I wanted to use a method reference to a records accessors. I wanted some way to get compile time type safety about the column I am requesting. If I change my User data type such that firstName now says first instead, I want all callers of my tool to get compile time errors. But I don't see how to do it. I really do think that, if records claim to be transparent carriers of data, then being able to isolate and point to a single RecordComponent in a type safe way that will fail at compile time if I am out of sorts sounds like a reasonable thing to want from a record. On Sun, Nov 30, 2025 at 3:04?PM Kirill Semyonkin wrote: > Hello David, > > I've seen some people (ab)use Serializable and SerializedLambda to get > names of the class and the method, with numerous examples like > https://stackoverflow.com/a/53397378/16208077. From there you can > traverse usual reflection with those strings to get the exact > RecordComponent or some other reflection object. But those strings > come from users doing method references, so you will get the behavior that > you wanted, at least to some extent. Although it slightly feels like an XY > problem. > > - Kirill Semyonkin > > ??, 30 ????. 2025??. ? 22:57, Attila Kelemen : > >> I guess, if your record type is fixed, then you can have a dummy instance >> of that record with all fields being different (hopefully, no 3 boolean >> components :)), and then you can do the same hack as with the interface + >> proxy combo. >> >> Attila Kelemen ezt ?rta (id?pont: 2025. >> nov. 30., V, 20:51): >> >>> I think that is impossible. What I did when I needed something similar >>> is that I used an interface instead of a record and built utilities around >>> it, because in that case you can imitate what you want. >>> >>> That is, consider that you have `interface User { String firstName(); >>> String lastName() }`. In this case, you could have methods taking a >>> `Function` and then you can create an instance of `User` via >>> `Proxy.newProxyInstance` in which you record which method was called, and >>> pass the proxy instance to the `Function`. Assuming that someone passed >>> `User::firstName` for the `Function`, you can detect which method was >>> passed. The drawbacks are obvious, but it is better than passing strings in >>> my opinion. >>> >>> David Alayachew ezt ?rta (id?pont: 2025. >>> nov. 30., V, 20:41): >>> >>>> Thanks for the response Attila. >>>> >>>> Let me try and loosen the constraints then -- is there any way for me >>>> to get a RecordComponent corresponding to firstName without needing to do >>>> String comparison? >>>> >>>> At the end of the day, that's all that I really need. >>>> >>>> As is now, the only way I can see to get a RecordComponent is to drill >>>> down from j.l.Class --> j.l.r.RecordComponent, then do String comparison >>>> against a provided String to get the record component that I want. That is >>>> unsafe and stringly typed, so, very much undesirable. After all, if I >>>> change my record to say first instead of firstName, I want a compiler >>>> error. But doing it that way, I won't -- I'll get a runtime error. >>>> >>>> So that's what I really want -- a type-safe way to isolate a record >>>> component from a record, without forcing my users to have to provide a >>>> String corresponding to the record component name. >>>> >>>> On Sun, Nov 30, 2025 at 2:16?PM Attila Kelemen < >>>> attila.kelemen85 at gmail.com> wrote: >>>> >>>>> I'm pretty sure there is no such thing, because that essentially >>>>> implies the existence of some kind of method literal (well, it would not be >>>>> strictly necessary, but the JLS would feel strange without it), and there >>>>> is no such thing (though it would be awesome, if there was). >>>>> >>>>> Also, note that if this was a thing, then your case is just a very >>>>> special case, and you would want more (I would for sure). That is, in that >>>>> case, I would also want type safety. So, something like >>>>> MethodReference<(MyRecord) -> String> (which of course would require >>>>> function types in Java). >>>>> >>>>> When I needed this, luckily I could restrain my need to interface >>>>> methods (as opposed to your record getters) where I could create a `Proxy` >>>>> and see which method gets called (nasty hack, has its downsides, but felt >>>>> like the safest to me). >>>>> >>>>> Attila >>>>> >>>>> David Alayachew ezt ?rta (id?pont: 2025. >>>>> nov. 29., Szo, 20:50): >>>>> >>>>>> And by all means, add more parameters to foo if you want. For >>>>>> example, if a User.class helps, please do so! >>>>>> >>>>>> I just don't want to do anything like this. >>>>>> >>>>>> foo("firstName"); >>>>>> >>>>>> That's stringly typed, and undesirable for my use case. >>>>>> >>>>> -------------- next part -------------- An HTML attachment was scrubbed... URL: From davidalayachew at gmail.com Sun Nov 30 21:01:31 2025 From: davidalayachew at gmail.com (David Alayachew) Date: Sun, 30 Nov 2025 16:01:31 -0500 Subject: Reflection on records In-Reply-To: References: Message-ID: I do invite more responses, but the responses I have received thus far (both public, private, and off the mailing list) all seem to say "it is not really possible with current tools". So, I will start a new thread talking about a feature request that would remedy this. On Sun, Nov 30, 2025 at 3:37?PM David Alayachew wrote: > Thanks everyone for the context. The answers I am getting are very > helpful. I do see a comment about XY problem, so here is the full context > of my problem. > > Unlike normal classes, record are transparent data carriers. Which make > them useful for simple DTO's and serialization. Specifically, I wanted to > create a De/serialization format for a CSV file. > > Let's say I have record User(String firstName, String lastName, > ComplexObject complexColumn) {}, and each RecordComponent corrsponds to a > column of my CSV, while each instance of User corresponds to a single row. > Let's also assume that firstName and lastName are computationally cheap to > deserialize, but complexColumn is expensive (complex but necessary regex). > > Well, I want to create a CSV De/Serialization tool that allows me to not > only deserialize the object in full, but also deserialize only the specific > component I want. In this case, if all I care about is firstName and > lastName, then why should I pay the price of also deserializing > complexColumn, which I won't use at all? > > Hence why I requested these various things in the thread -- such as the > ability to reference RecordComponents, or why I wanted to use a method > reference to a records accessors. I wanted some way to get compile time > type safety about the column I am requesting. If I change my User data type > such that firstName now says first instead, I want all callers of my tool > to get compile time errors. But I don't see how to do it. > > I really do think that, if records claim to be transparent carriers of > data, then being able to isolate and point to a single RecordComponent in a > type safe way that will fail at compile time if I am out of sorts sounds > like a reasonable thing to want from a record. > > > On Sun, Nov 30, 2025 at 3:04?PM Kirill Semyonkin > wrote: > >> Hello David, >> >> I've seen some people (ab)use Serializable and SerializedLambda to get >> names of the class and the method, with numerous examples like >> https://stackoverflow.com/a/53397378/16208077. From there you can >> traverse usual reflection with those strings to get the exact >> RecordComponent or some other reflection object. But those strings >> come from users doing method references, so you will get the behavior that >> you wanted, at least to some extent. Although it slightly feels like an XY >> problem. >> >> - Kirill Semyonkin >> >> ??, 30 ????. 2025??. ? 22:57, Attila Kelemen > >: >> >>> I guess, if your record type is fixed, then you can have a dummy >>> instance of that record with all fields being different (hopefully, no 3 >>> boolean components :)), and then you can do the same hack as with the >>> interface + proxy combo. >>> >>> Attila Kelemen ezt ?rta (id?pont: 2025. >>> nov. 30., V, 20:51): >>> >>>> I think that is impossible. What I did when I needed something similar >>>> is that I used an interface instead of a record and built utilities around >>>> it, because in that case you can imitate what you want. >>>> >>>> That is, consider that you have `interface User { String firstName(); >>>> String lastName() }`. In this case, you could have methods taking a >>>> `Function` and then you can create an instance of `User` via >>>> `Proxy.newProxyInstance` in which you record which method was called, and >>>> pass the proxy instance to the `Function`. Assuming that someone passed >>>> `User::firstName` for the `Function`, you can detect which method was >>>> passed. The drawbacks are obvious, but it is better than passing strings in >>>> my opinion. >>>> >>>> David Alayachew ezt ?rta (id?pont: 2025. >>>> nov. 30., V, 20:41): >>>> >>>>> Thanks for the response Attila. >>>>> >>>>> Let me try and loosen the constraints then -- is there any way for me >>>>> to get a RecordComponent corresponding to firstName without needing to do >>>>> String comparison? >>>>> >>>>> At the end of the day, that's all that I really need. >>>>> >>>>> As is now, the only way I can see to get a RecordComponent is to drill >>>>> down from j.l.Class --> j.l.r.RecordComponent, then do String comparison >>>>> against a provided String to get the record component that I want. That is >>>>> unsafe and stringly typed, so, very much undesirable. After all, if I >>>>> change my record to say first instead of firstName, I want a compiler >>>>> error. But doing it that way, I won't -- I'll get a runtime error. >>>>> >>>>> So that's what I really want -- a type-safe way to isolate a record >>>>> component from a record, without forcing my users to have to provide a >>>>> String corresponding to the record component name. >>>>> >>>>> On Sun, Nov 30, 2025 at 2:16?PM Attila Kelemen < >>>>> attila.kelemen85 at gmail.com> wrote: >>>>> >>>>>> I'm pretty sure there is no such thing, because that essentially >>>>>> implies the existence of some kind of method literal (well, it would not be >>>>>> strictly necessary, but the JLS would feel strange without it), and there >>>>>> is no such thing (though it would be awesome, if there was). >>>>>> >>>>>> Also, note that if this was a thing, then your case is just a very >>>>>> special case, and you would want more (I would for sure). That is, in that >>>>>> case, I would also want type safety. So, something like >>>>>> MethodReference<(MyRecord) -> String> (which of course would require >>>>>> function types in Java). >>>>>> >>>>>> When I needed this, luckily I could restrain my need to interface >>>>>> methods (as opposed to your record getters) where I could create a `Proxy` >>>>>> and see which method gets called (nasty hack, has its downsides, but felt >>>>>> like the safest to me). >>>>>> >>>>>> Attila >>>>>> >>>>>> David Alayachew ezt ?rta (id?pont: 2025. >>>>>> nov. 29., Szo, 20:50): >>>>>> >>>>>>> And by all means, add more parameters to foo if you want. For >>>>>>> example, if a User.class helps, please do so! >>>>>>> >>>>>>> I just don't want to do anything like this. >>>>>>> >>>>>>> foo("firstName"); >>>>>>> >>>>>>> That's stringly typed, and undesirable for my use case. >>>>>>> >>>>>> -------------- next part -------------- An HTML attachment was scrubbed... URL: From scolebourne at joda.org Sun Nov 30 21:05:11 2025 From: scolebourne at joda.org (Stephen Colebourne) Date: Sun, 30 Nov 2025 21:05:11 +0000 Subject: Reflection on records In-Reply-To: References: Message-ID: There is a way to do this, but it isn't pretty. Use annotation processing. @GeneratedRecordComponentInterface record User(String firstName, String lastName, ComplexObject complexColumn) implements UserColumns {} // annotation processor generates: public interface UserColumns { public static final RecordComponentWrapper FIRST_NAME_COMPONENT = new RecordComponentWrapper(User.class, "firstName"); public static final RecordComponentWrapper LAST_NAME_COMPONENT = new RecordComponentWrapper(User.class, "lastName"); public static final RecordComponentWrapper COMPLEX_COLUMN_COMPONENT = new RecordComponentWrapper(User.class, "complexColumn"); } where `RecordComponentWrapper` is some suitable type-safe wrapper for record components. Although there is a string for each record component, it is in generated code, thus won't get out of sync. (This is the annotation processing equivalent to how Joda-Beans meta-properties have worked for many years) Stephen On Sun, 30 Nov 2025 at 20:39, David Alayachew wrote: > > Thanks everyone for the context. The answers I am getting are very helpful. I do see a comment about XY problem, so here is the full context of my problem. > > Unlike normal classes, record are transparent data carriers. Which make them useful for simple DTO's and serialization. Specifically, I wanted to create a De/serialization format for a CSV file. > > Let's say I have record User(String firstName, String lastName, ComplexObject complexColumn) {}, and each RecordComponent corrsponds to a column of my CSV, while each instance of User corresponds to a single row. Let's also assume that firstName and lastName are computationally cheap to deserialize, but complexColumn is expensive (complex but necessary regex). > > Well, I want to create a CSV De/Serialization tool that allows me to not only deserialize the object in full, but also deserialize only the specific component I want. In this case, if all I care about is firstName and lastName, then why should I pay the price of also deserializing complexColumn, which I won't use at all? > > Hence why I requested these various things in the thread -- such as the ability to reference RecordComponents, or why I wanted to use a method reference to a records accessors. I wanted some way to get compile time type safety about the column I am requesting. If I change my User data type such that firstName now says first instead, I want all callers of my tool to get compile time errors. But I don't see how to do it. > > I really do think that, if records claim to be transparent carriers of data, then being able to isolate and point to a single RecordComponent in a type safe way that will fail at compile time if I am out of sorts sounds like a reasonable thing to want from a record. > > > On Sun, Nov 30, 2025 at 3:04?PM Kirill Semyonkin wrote: >> >> Hello David, >> >> I've seen some people (ab)use Serializable and SerializedLambda to get names of the class and the method, with numerous examples like https://stackoverflow.com/a/53397378/16208077. From there you can traverse usual reflection with those strings to get the exact RecordComponent or some other reflection object. But those strings come from users doing method references, so you will get the behavior that you wanted, at least to some extent. Although it slightly feels like an XY problem. >> >> - Kirill Semyonkin >> >> ??, 30 ????. 2025??. ? 22:57, Attila Kelemen : >>> >>> I guess, if your record type is fixed, then you can have a dummy instance of that record with all fields being different (hopefully, no 3 boolean components :)), and then you can do the same hack as with the interface + proxy combo. >>> >>> Attila Kelemen ezt ?rta (id?pont: 2025. nov. 30., V, 20:51): >>>> >>>> I think that is impossible. What I did when I needed something similar is that I used an interface instead of a record and built utilities around it, because in that case you can imitate what you want. >>>> >>>> That is, consider that you have `interface User { String firstName(); String lastName() }`. In this case, you could have methods taking a `Function` and then you can create an instance of `User` via `Proxy.newProxyInstance` in which you record which method was called, and pass the proxy instance to the `Function`. Assuming that someone passed `User::firstName` for the `Function`, you can detect which method was passed. The drawbacks are obvious, but it is better than passing strings in my opinion. >>>> >>>> David Alayachew ezt ?rta (id?pont: 2025. nov. 30., V, 20:41): >>>>> >>>>> Thanks for the response Attila. >>>>> >>>>> Let me try and loosen the constraints then -- is there any way for me to get a RecordComponent corresponding to firstName without needing to do String comparison? >>>>> >>>>> At the end of the day, that's all that I really need. >>>>> >>>>> As is now, the only way I can see to get a RecordComponent is to drill down from j.l.Class --> j.l.r.RecordComponent, then do String comparison against a provided String to get the record component that I want. That is unsafe and stringly typed, so, very much undesirable. After all, if I change my record to say first instead of firstName, I want a compiler error. But doing it that way, I won't -- I'll get a runtime error. >>>>> >>>>> So that's what I really want -- a type-safe way to isolate a record component from a record, without forcing my users to have to provide a String corresponding to the record component name. >>>>> >>>>> On Sun, Nov 30, 2025 at 2:16?PM Attila Kelemen wrote: >>>>>> >>>>>> I'm pretty sure there is no such thing, because that essentially implies the existence of some kind of method literal (well, it would not be strictly necessary, but the JLS would feel strange without it), and there is no such thing (though it would be awesome, if there was). >>>>>> >>>>>> Also, note that if this was a thing, then your case is just a very special case, and you would want more (I would for sure). That is, in that case, I would also want type safety. So, something like MethodReference<(MyRecord) -> String> (which of course would require function types in Java). >>>>>> >>>>>> When I needed this, luckily I could restrain my need to interface methods (as opposed to your record getters) where I could create a `Proxy` and see which method gets called (nasty hack, has its downsides, but felt like the safest to me). >>>>>> >>>>>> Attila >>>>>> >>>>>> David Alayachew ezt ?rta (id?pont: 2025. nov. 29., Szo, 20:50): >>>>>>> >>>>>>> And by all means, add more parameters to foo if you want. For example, if a User.class helps, please do so! >>>>>>> >>>>>>> I just don't want to do anything like this. >>>>>>> >>>>>>> foo("firstName"); >>>>>>> >>>>>>> That's stringly typed, and undesirable for my use case. From davidalayachew at gmail.com Sun Nov 30 21:18:49 2025 From: davidalayachew at gmail.com (David Alayachew) Date: Sun, 30 Nov 2025 16:18:49 -0500 Subject: Reflection on records In-Reply-To: References: Message-ID: Thanks Stephen. Hmmmmm, so this is definitely the best solution I have seen thus far. The only real downside is that the static final field has a different name than the actual record component. But I can probably fix that by making it an inner class or something, as opposed to sharing the same namespace as the record itself. Can you link me to the annotation code? On Sun, Nov 30, 2025 at 4:05?PM Stephen Colebourne wrote: > There is a way to do this, but it isn't pretty. Use annotation processing. > > @GeneratedRecordComponentInterface > record User(String firstName, String lastName, ComplexObject > complexColumn) implements UserColumns {} > > // annotation processor generates: > public interface UserColumns { > public static final RecordComponentWrapper > FIRST_NAME_COMPONENT = new RecordComponentWrapper(User.class, > "firstName"); > public static final RecordComponentWrapper > LAST_NAME_COMPONENT = new RecordComponentWrapper(User.class, > "lastName"); > public static final RecordComponentWrapper > COMPLEX_COLUMN_COMPONENT = new RecordComponentWrapper(User.class, > "complexColumn"); > } > > where `RecordComponentWrapper` is some suitable type-safe wrapper for > record components. > > Although there is a string for each record component, it is in > generated code, thus won't get out of sync. > > (This is the annotation processing equivalent to how Joda-Beans > meta-properties have worked for many years) > Stephen > > On Sun, 30 Nov 2025 at 20:39, David Alayachew > wrote: > > > > Thanks everyone for the context. The answers I am getting are very > helpful. I do see a comment about XY problem, so here is the full context > of my problem. > > > > Unlike normal classes, record are transparent data carriers. Which make > them useful for simple DTO's and serialization. Specifically, I wanted to > create a De/serialization format for a CSV file. > > > > Let's say I have record User(String firstName, String lastName, > ComplexObject complexColumn) {}, and each RecordComponent corrsponds to a > column of my CSV, while each instance of User corresponds to a single row. > Let's also assume that firstName and lastName are computationally cheap to > deserialize, but complexColumn is expensive (complex but necessary regex). > > > > Well, I want to create a CSV De/Serialization tool that allows me to not > only deserialize the object in full, but also deserialize only the specific > component I want. In this case, if all I care about is firstName and > lastName, then why should I pay the price of also deserializing > complexColumn, which I won't use at all? > > > > Hence why I requested these various things in the thread -- such as the > ability to reference RecordComponents, or why I wanted to use a method > reference to a records accessors. I wanted some way to get compile time > type safety about the column I am requesting. If I change my User data type > such that firstName now says first instead, I want all callers of my tool > to get compile time errors. But I don't see how to do it. > > > > I really do think that, if records claim to be transparent carriers of > data, then being able to isolate and point to a single RecordComponent in a > type safe way that will fail at compile time if I am out of sorts sounds > like a reasonable thing to want from a record. > > > > > > On Sun, Nov 30, 2025 at 3:04?PM Kirill Semyonkin > wrote: > >> > >> Hello David, > >> > >> I've seen some people (ab)use Serializable and SerializedLambda to get > names of the class and the method, with numerous examples like > https://stackoverflow.com/a/53397378/16208077. From there you can > traverse usual reflection with those strings to get the exact > RecordComponent or some other reflection object. But those strings come > from users doing method references, so you will get the behavior that you > wanted, at least to some extent. Although it slightly feels like an XY > problem. > >> > >> - Kirill Semyonkin > >> > >> ??, 30 ????. 2025??. ? 22:57, Attila Kelemen < > attila.kelemen85 at gmail.com>: > >>> > >>> I guess, if your record type is fixed, then you can have a dummy > instance of that record with all fields being different (hopefully, no 3 > boolean components :)), and then you can do the same hack as with the > interface + proxy combo. > >>> > >>> Attila Kelemen ezt ?rta (id?pont: 2025. > nov. 30., V, 20:51): > >>>> > >>>> I think that is impossible. What I did when I needed something > similar is that I used an interface instead of a record and built utilities > around it, because in that case you can imitate what you want. > >>>> > >>>> That is, consider that you have `interface User { String firstName(); > String lastName() }`. In this case, you could have methods taking a > `Function` and then you can create an instance of `User` via > `Proxy.newProxyInstance` in which you record which method was called, and > pass the proxy instance to the `Function`. Assuming that someone passed > `User::firstName` for the `Function`, you can detect which method was > passed. The drawbacks are obvious, but it is better than passing strings in > my opinion. > >>>> > >>>> David Alayachew ezt ?rta (id?pont: 2025. > nov. 30., V, 20:41): > >>>>> > >>>>> Thanks for the response Attila. > >>>>> > >>>>> Let me try and loosen the constraints then -- is there any way for > me to get a RecordComponent corresponding to firstName without needing to > do String comparison? > >>>>> > >>>>> At the end of the day, that's all that I really need. > >>>>> > >>>>> As is now, the only way I can see to get a RecordComponent is to > drill down from j.l.Class --> j.l.r.RecordComponent, then do String > comparison against a provided String to get the record component that I > want. That is unsafe and stringly typed, so, very much undesirable. After > all, if I change my record to say first instead of firstName, I want a > compiler error. But doing it that way, I won't -- I'll get a runtime error. > >>>>> > >>>>> So that's what I really want -- a type-safe way to isolate a record > component from a record, without forcing my users to have to provide a > String corresponding to the record component name. > >>>>> > >>>>> On Sun, Nov 30, 2025 at 2:16?PM Attila Kelemen < > attila.kelemen85 at gmail.com> wrote: > >>>>>> > >>>>>> I'm pretty sure there is no such thing, because that essentially > implies the existence of some kind of method literal (well, it would not be > strictly necessary, but the JLS would feel strange without it), and there > is no such thing (though it would be awesome, if there was). > >>>>>> > >>>>>> Also, note that if this was a thing, then your case is just a very > special case, and you would want more (I would for sure). That is, in that > case, I would also want type safety. So, something like > MethodReference<(MyRecord) -> String> (which of course would require > function types in Java). > >>>>>> > >>>>>> When I needed this, luckily I could restrain my need to interface > methods (as opposed to your record getters) where I could create a `Proxy` > and see which method gets called (nasty hack, has its downsides, but felt > like the safest to me). > >>>>>> > >>>>>> Attila > >>>>>> > >>>>>> David Alayachew ezt ?rta (id?pont: > 2025. nov. 29., Szo, 20:50): > >>>>>>> > >>>>>>> And by all means, add more parameters to foo if you want. For > example, if a User.class helps, please do so! > >>>>>>> > >>>>>>> I just don't want to do anything like this. > >>>>>>> > >>>>>>> foo("firstName"); > >>>>>>> > >>>>>>> That's stringly typed, and undesirable for my use case. > -------------- next part -------------- An HTML attachment was scrubbed... URL: From davidalayachew at gmail.com Sun Nov 30 21:50:22 2025 From: davidalayachew at gmail.com (David Alayachew) Date: Sun, 30 Nov 2025 16:50:22 -0500 Subject: Feature Request -- Enumerate the RecordComponents of a record Message-ID: Hello @amber-dev , (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: