Let me replay some analysis that was done on this topic in the past.
There are two separate things going on here:
- Can we use symbolic constants instead of string constants to do reflective
lookups
- Can we have more kinds of symbolic reflective constants (field literals,
method literals, record component literals, method handle literals, etc.)
The first one is more shallow; David is exploiting a special case of records
where (a) there is already a method reference form for accessors, which could
potentially be bootstrapped into service here and (b) very luckily, the shape
of all such accessor method references vary only parametrically in shape. So
one could write a method:
interface AccessorShape<T, U> {
U access(T t);
}
<R extends Record, U> RecordComponent component(Accessor<R, U> c) { … }
Which would allow us to say
RecordComponent rc = component(Foo::component)
Where the parameter is a method reference but from which we can strip-mine the
name and type and turn it into a component lookup. That’s a clever trick, and
there is no intrinsic reason why we couldn’t do this, but it doesn’t scale
beyond this particular case. Field and method lookups would still use strings
and could fail at runtime for all the reasons.
The second is one that was explored fairly deeply during Lambda. Reflective
literals for jlr.{Field,Method,Constructor} are an obvious move, and have a few
challenges, some of which are workable, but the biggest of which is:
overloading. With method reference targeted at functional interfaces, the
functional interface provides a signature shape with which we can do overload
selection. But if we had an overloaded method m, then
Method m = Foo::m
We have no information with which to select the proper m. (Please, don’t take
this as an invitation for a syntax discussion; they’ve all been explored, and
besides, there are deeper problems here than syntax.)
On Dec 1, 2025, at 12:13 PM, Archie Cobbs
<[email protected]<mailto:[email protected]>> wrote:
I'm guessing what underlies David's question is this thought: Why can't the
compiler provide more compile-time checking of Field and Method reflection
objects?
After all, it does this for Class objects by providing us with Class literals
(remember in the old days you could only obtain them via Class.forName()).
I have wondered the same thing, though I also appreciate that the devil is in
the details.
For example, David's question could be addressed by adding Method and Field
literals:
public class Foo {
public static void meth(int x) { ... }
}
Method m = Foo::meth.method;
m.invoke(123);
Of course, this is still imprecise because Method is not generic and so this
would fail if there were overloads, among other problems.
So I think the intuition is valid. Whether a practical solution exists is
another question.
-Archie
On Mon, Dec 1, 2025 at 10:46 AM Chen Liang
<[email protected]<mailto:[email protected]>> wrote:
Hi David, before we investigate solutions, what is the problem you want to
resolve?
If you want to obtain a Method on a record class, you can do
recordClass.getMethod("variable") to find that accessor method.
Note that the Java Virtual Machine does not validate a record, that it may
recognize a class with the record attribute but has no corresponding accessor
methods or canonical constructor as a record class.
--
Archie L. Cobbs