Constructing records through reflection and module restrictions

Remi Forax forax at univ-mlv.fr
Sat Dec 7 22:34:08 UTC 2024


----- Original Message -----
> From: "Florian Weimer" <fw at deneb.enyo.de>
> To: "Brian Goetz" <brian.goetz at oracle.com>
> Cc: "amber-dev" <amber-dev at openjdk.org>
> Sent: Saturday, December 7, 2024 9:35:56 PM
> Subject: Re: Constructing records through reflection and module restrictions

> * Brian Goetz:
> 
>> Let’s take about 100 steps back. Why do you think that records
>> should be immune to the ordinary access control of the language?
> 
> I think of them of named tuples.  Tuples don't have this type of
> access control.  But of course, one could argue that once names are
> involved, the matter of access control arises.  I had not considered
> this.
> 
>> And why are you focusing only on the constructor and not the other
>> members of the record that presumably would be needed to access its
>> state?  Why is modularity special here and not private records?
> 
> It's true that similar considerations applies to component access.
> This can sometimes be worked around by implementing a suitable
> interface.
> 
>> There are a whole host of assumptions in this line of thinking, and
>> I think we should start at the beginning. What problem are you
>> trying to solve?
> 
> Syntax-wise, it is very tempting to use this with very localized
> record types for various kinds of custom deserialization scenarios.
> For example, to read a CSV file with two colums, something like this
> could be used:
> 
>            record Row(String name, int index) {}
>            var csv = CSVReader.newReader(r, Row.class);
>            while (true) {
>                var row = csv.readRow();
>                if (row == null)
>                    break;
>                // Use the row variable.
>                ...
>            }
> 
> But it would equally work for SQL result set rows, binary structures,
> and so on.

Why not sending the lookup object here :

var csv = CSVReader.newReader(r, Row.class, MethodHandles.lookup());

> 
> I think some people use interfaces and java.lang.reflect.Proxy for a
> similar purpose, hoping that method declaration order matches
> reflection order (not a good idea, I know).  As far as I can see, the
> proxy mechanism does not perform a module encapsulation check and can
> create instaces at points where a regular class declaration with an
> implements clause could not reference to the interface.  Records would
> be a better replacement because they provide ordering of components.

If you use an abstract deconstructors/pattern method, you get the declaration order

  interface Row {
    abstract deconstructor (String name, int index) Row();   // or a similar syntax
  }

  ...
  Row(var name, var index) = csv.readRow(); 
  // use name and index here

and i suppose that j.l.r.Proxy will be updated to implement such pattern.

regards,
Rémi


More information about the amber-dev mailing list