On Nov 3, 2017, at 1:26 AM, Patrick Reinhart <patr...@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