List.copyOf already does what you want.

https://github.com/openjdk/jdk/blob/master/src/java.base/share/classes/java/util/List.java#L1068
https://github.com/openjdk/jdk/blob/master/src/java.base/share/classes/java/util/ImmutableCollections.java#L168

Paul.

> On Aug 23, 2022, at 4:49 PM, Ethan McCue <et...@mccue.dev> wrote:
> 
> Hi all,
> 
> I am running into an issue with the collections framework where I have to 
> choose between good semantics for users and performance.
> 
> Specifically I am taking a java.util.List from my users and I need to choose 
> to either
> * Not defensively copy and expose a potential footgun when I pass that List 
> to another thread
> * Defensively copy and make my users pay an unnecessary runtime cost.
> 
> What I would really want, in a nutshell, is for List.copyOf to be a no-op 
> when used on lists made with List.of().
> 
> Below the line is a pitch I wrote up on reddit 7 months ago for a mechanism I 
> think could accomplish that. My goal is to share the idea a bit more widely 
> and to this specific audience to get feedback.
> 
> https://www.reddit.com/r/java/comments/sf8qrv/comment/hv8or92/?utm_source=share&utm_medium=web2x&context=3
>  
> 
> Important also for context is Ron Pressler's comment above.
> --------------
> 
> What if the collections api added more marker interfaces like RandomAccess?
> 
> It's already a common thing for codebases to make explicit null checks at 
> error boundaries because the type system can't encode null | List<String>. 
> 
> This feels like a similar problem.
> If you have a List<T> in the type system then you don't know for sure you can 
> call any methods on it until you check that its not null. In the same way, 
> there is a set of methods that you don't know at the type/interface level if 
> you are allowed to call.
> 
> If the List is actually a __
> Then you can definitely call
> And you know other reference holders might call
> And you can confirm its this case by
> null
> no methods
> no methods
> list == null
> List.of(...)
> get, size
> get, size
> ???
> Collections.unmodifiableList(...)
> get, size
> get, size, add, set
> ???
> Arrays.asList(...)
> get, size, set
> get, size, set
> ???
> new ArrayList<>()
> get, size, add, set
> get, size, add, set
> ???
> While yes, there is no feasible way to encode these things in the type 
> system. Its not impossible to encode it at runtime though.
> interface FullyImmutable {
> // So you know the existence of this implies the absence
> // of the others
> default Void cantIntersect() { return null; }
> }
> 
> interace MutationCapability {
> default String cantIntersect() { return ""; }
> }
> 
> interface Addable extends MutationCapability {}
> interface Settable extends MutationCapability {}
> 
> If the List is actually a __
> Then you can definitely call
> And you know other reference holders might call
> And you can confirm its this case by
> null
> no methods
> no methods
> list == null
> List.of(...)
> get, size
> get, size
> instanceof FullyImmutable
> Collections.unmodifiableList(...)
> get, size
> get, size, add, set
> !(instanceof Addable) && !(instanceof Settable)
> Arrays.asList(...)
> get, size, set
> get, size, set
> instanceof Settable
> new ArrayList<>()
> get, size, add, set
> get, size, add, set
> instanceof Settable && instanceof Addable
> In the same way a RandomAccess check let's implementations decide whether 
> they want to try an alternative algorithm or crash, some marker "capability" 
> interfaces would let users of a collection decide if they want to clone what 
> they are given before working on it.
> 
> 
> --------------
> 
> So the applicability of this would be that the list returned by List.of could 
> implement FullyImmutable, signifying that there is no caller which might have 
> a mutable handle on the collection. Then List.of could check for this 
> interface and skip a copy.
> 
> 

Reply via email to