[External] : Re: Method and Field Literals

Ethan McCue ethan at mccue.dev
Sun Apr 24 15:55:45 UTC 2022


> Is "externalUncheckedName" a method name there?

It would be the name of a symbol in a linked DLL/SO.

I think this pattern comes down to effectively "I have knowledge about how
this system outside of Java's compiler and type system should work, how do
I teach Java about it"

- For the Panama case, you have the C header files, you know what the Java
API needs to be.
- For the Method/Field reflection case, you have the methods and fields in
another corner of the type system
- For the SQL case, you have the available table and column names
hypothetically available from the sum of migrations or a dump of the state
of your DB

What makes it feel strange is that in a mostly closed world, like many
web applications, your methods are constant. What is available reflectively
at runtime is actually known at compile time. If you want to see this
assumption be thoroughly broken, you should see the code people write for
interacting with divergent minecraft versions.

https://github.com/CryptoMorin/XSeries/blob/master/src/main/java/com/cryptomorin/xseries/ReflectionUtils.java#L124

If you want a typed api for an externally defined resource, it seems the
route to go is either to write "unsafe" code yourself or generate it.

- For Panama, the jextract tool takes a C header and encodes its knowledge
of the C type system into Java.
- For Method/Field reflection, if you assume a closed world you can use
that knowledge to codegen ways for access to be checked
- For SQL, you can dump Java code which encodes some degree of your
knowledge about what will be safe to access in the database (column name
constants, full JOOQ, etc)



On Sun, Apr 24, 2022 at 11:31 AM Brian Goetz <brian.goetz at oracle.com> wrote:

> So, a feature where field and method literals evaluated only to Method
> objects is a pretty weak one, and worse, fi the goal is merely to pull the
> reflection API into the language, is likely to result in requests to pull
> further.  Though I do enjoy the extra type checking that IntelliJ gives me
> for method and method handle lookup.)
>
> The reality is that Method is not a very useful type; reflection is an
> escape hatch, which has more benefit for frameworks than for ordinary user
> code.  You might say “but we have class literals”, but this is mostly a
> “for consistency” argument*, and one that doesn’t even survive much
> scrutiny.
>
> Class literals have two aspects that method literals would not: their role
> in inference (Foo.class has type Class<Foo>, meaning that it can be used as
> a source of constraints in type inference), and the Object::getClass
> method.  Method and field literals would have neither of these two touch
> points.  (If it were not for the type inference aspect, if we didn’t have
> class literals now, I might not be inclined to add them — Class::forName
> works  too.)  So I would rate this a pretty weak feature.
>
> The main reason method references are useful and these are less useful is
> that methods have behavior, and method refs allow you to access that
> behavior through the suitable abstraction level (e.g., Function, Supplier.)
>  Passing around Method or MethodHandle or VarHandle is not particularly
> desirable for ordinary application code.
>
> There’s a version of method (and field) references that is more
> interesting, where we can use target typing to let Foo::bar evaluate to a
> SAM type, Method, MethodHandle, MethodDesc, or other description of a
> method.  (Note that you also have to pull in additional syntax and behavior
> to support overload selection, since we don’t have a SAM type to guide the
> overload selection.)  That’s more interesting, but a more complex feature.
> Fields are even more complicated, because fields have TWO behaviors, and
> the obvious representations (Field, VarHandle) are also pretty low-level
> and unsuitable to application-level interaction.  (If the language had
> Properties, then turning a field into a Property would be a more
> appropriate API-level encoding.)
>
>
> *If the best argument you can make for a feature is “for consistency”,
> that’s usually a sign that the feature is weak.
>
>
>
> On Apr 24, 2022, at 5:31 AM, arjan tijms <arjan.tijms at gmail.com> wrote:
>
> Hi,
>
> On Sun, Apr 24, 2022 at 1:17 AM Ethan McCue <ethan at mccue.dev> wrote:
>
>> Before moving on with the discussion, can you also address Brain Goetz's
>> questions directly?
>>
>> 1. what do you expect the _type_ of a method literal is?
>>
>
> java.lang.Method
>
>
> 2. Is it a goal to have
>>     a. earlier error checking that you specified a method that exists
>>     b. syntactic sugar for the reflective call
>>     c. the lookup can be more efficient
>>
>
> a.
>
>
> And then from me
>>
>> 3. What in your first example disqualifies a normal method reference
>> lambda (Class::method) from being appropriate?
>>
>
> If you mean the Query example:
>
> criteriaQuery.select(root).where(cb.equal(root.get(Student_.gradYear),
> 2015));
>
> Then it's not about the actual value of Student.gradYear at this point,
> but about the identity of the property. It's used to (ultimately) generate
> SQL. The property (field, method) needs to be identified, in order to
> read annotations from it that specify the mapping.
>
> If you mean the handler and interceptor examples, then it's checking that
> an invoked (intercepted / handled) method is the intended method.
>
>
>
>> 4. This pattern of
>>
>>     var thing = Lookup.find("externalUncheckedName", TypeA.class,
>> TypeB.class)
>>     var result = (TypeB) thing.invoke(new TypeA()); // Object... as arg
>> type and throws some exceptions
>>
>> is also used in the API for Panama. If we are going to add new goo, is
>> there a way to address this sort of API as well?
>>
>
> Is "externalUncheckedName" a method name there?
>
> Kind regards,
> Arjan Tijms
>
>
>


More information about the discuss mailing list