You'll need to write the annotation processor yourself I'm afraid, this is a design outline. Stephen
On Sun, 30 Nov 2025, 21:19 David Alayachew, <[email protected]> wrote: > 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 <[email protected]> > 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<String> >> FIRST_NAME_COMPONENT = new RecordComponentWrapper(User.class, >> "firstName"); >> public static final RecordComponentWrapper<String> >> LAST_NAME_COMPONENT = new RecordComponentWrapper(User.class, >> "lastName"); >> public static final RecordComponentWrapper<ComplexObject> >> 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 <[email protected]> >> 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 <[email protected]> >> 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 < >> [email protected]>: >> >>> >> >>> 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 <[email protected]> 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<User, T>` 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 <[email protected]> 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 < >> [email protected]> 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 <[email protected]> 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. >> >
