RFR(m): 8177290 add copy factory methods for unmodifiable List, Set, Map

Remi Forax forax at univ-mlv.fr
Sat Nov 18 10:41:29 UTC 2017


Hi John,
i strongly believe that static fluent methods have no place in a blue collar language, we can do better, in fact the have already done better by introducing default method instead of extension methods like in C# or Kotlin*.

The main issue with this kind of method is that it quacks like a duck but it's not a duck, i.e. you call those static methods as virtual methods but there are no virtual methods because you can not override them. 

Adding extension methods as feature is like a black hole, extension methods allow you to write clunky DSLs so it's a feature that will force the language to move to add more new features to be able to write decent DSLs (think implicit object as an example), and so on. So it sucks your design budget like a black hole.

In term of performance, the code inside a static extension methods tends to become megamorphic, in C#, Data Link (Link for Collection API) is slow because of that, in Kotlin you can workaround that by using the keyword inline which will copy the code into the callsite avoiding profile pollution.

So in my opinion, the only possible option is to introduce final default methods, i fully understand that this is non trivial to introduce this kind of methods in the VM but this discussion is a good use case for their introduction. 

regards,
Rémi

* i will not criticize Kotlin designers on that, they wanted to enhance Java APIs without owning them so they had little options.

----- Mail original -----
> De: "John Rose" <john.r.rose at oracle.com>
> À: "Patrick Reinhart" <patrick at reini.net>
> Cc: "core-libs-dev" <core-libs-dev at openjdk.java.net>
> Envoyé: Samedi 18 Novembre 2017 07:40:05
> Objet: Re: RFR(m): 8177290 add copy factory methods for unmodifiable List, Set, Map

> On Nov 3, 2017, at 1:26 AM, Patrick Reinhart <patrick at reini.net> wrote:
>> 
>>> 
>>> On 11/1/2017 4:29 PM, Patrick Reinhart wrote:
>>>> In this case I would prefer a non static copyOf() method on the list
>>>> to create a unmodifiable list/set/map, where the optimal factory
>>>> method can be called. This would also solve the problem of a
>>>> concurrent implementation.
> 
> Such methods would, unfortunately, be a disastrous mistake.
> 
> We are encouraging users to rely on the unmodifiability of the
> value-based lists, sets, and maps returned by copyOf, the
> same way they rely on the unmodifiability of Strings.  But
> if we made copyOf be non-static, then an attacker (or just
> a buggy program) could introduce a broken implementation
> of List that returned a time-varying List.  This would break
> the contract of copyOf, but it would be impossible to detect.
> The result would be a less reliable copyOf API, and
> eventually some TOCTTOU security vulnerabilities.
> This kind of surprise mutability is red meat for security
> researchers.
> 
> So it's got to be a static method, although if List were a
> class we could also choose to make copyOf be a final method.
> 
> I said "unfortunately" above because I too would prefer
> fluent syntax like ls.unmodifiableCopy() or ls.frozen()
> instead of List.copyOf(ls), since fluent syntax reads
> and composes cleanly from left to right.
> 
> I think a good way to get what we want may be to
> introduce a way for selected methods of an interface
> to mark themselves (somehow) as "fluent statics",
> meaning that they can be invoked with their first
> argument in receiver position, before the dot.
> In effect, they would act like "final default" methods
> but without having to damage interfaces with final
> methods.
> 
> I don't have a syntax in mind for defining a "fluent
> static", but I have thought for some time that allowing
> such sugar for interface statics is the best way to
> adapt the notion of class final methods to interfaces.
> 
> This is not easy to do, since it is a language change,
> and only applies to a small (though influential) number of
> methods, those which should *not* be overridable but
> *should* (for some reason of API design) support virtual
> (fluent, postfix, left-to-right) notation.
> 
> For more details please see JDK-8191530 and if you
> think of a good use case for these thingies, let me know
> so I can add it to the write-up.
> 
> — John


More information about the core-libs-dev mailing list