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.