On 9/2/25 5:00 AM, Eirik Bjørsnøs wrote:
On Tue, Sep 2, 2025 at 1:46 PM Eirik Bjørsnøs <[email protected]> wrote:

Interestingly, List.copyOf [4] explicitly specifies that modifications
to the given Collection are not reflected in the returned List. (Even
when this may be inferred from the method name!). This prose is what I
feel may be missing from List.of(E... elements).

TLDR:

I think my long-winded question boils down to:

Should we add something like the following to List.of(E... elements):

      * If the given array is subsequently modified, the returned List will not
      * reflect such modifications.

This would clarify this aspect and provide parity with List.copyOf.

If somebody is genuinely confused by the situation, we could add some clarifications. I'll observe though that the Java API specifications rely on the reader to have a lot of implicit knowledge. In a sense, this is a weakness of the specifications. But if we didn't rely on implicit knowledge, the specifications would be unbearably cumbersome and verbose.

The implicit knowledge I'm referring to is that, in general, the internal state of objects in the API is rarely aliased with the state of other objects. This is so pervasive that it's hardly stated anywhere. Arrays.asList is a notable exception, which is why people find it confusing, and it's why Venkat and others (including me!) talk about this issue in presentations. The various collections views (e.g., subList, Map.entrySet, etc.) are also exceptions, and the specs go to some effort to make this clear -- because they're exceptional cases.

The reason that List.copyOf's spec is explicit about modifications is that it needs to specify that it "makes a copy" while sometimes being allowed not to make a copy! That is, we wanted to allow List.copyOf to return its argument if the argument is unmodifiable. However, we didn't want to specify the exact circumstances under which this occurs. For the same reason, we didn't want to specify that List.copyOf always makes a copy, as it would preclude this optimization. The "modifications are not reflected" clause is a bit of specification language that allows us to split the difference. We avoid making any statements about the identity of the returned object, but we preserve essential behavior that a mutable collection is copied.

This mostly doesn't apply to List.of(...) though it can if you look really hard. Most people's experience of List.of is something like

   var list = List.of(a, b, c, ..., x, y, z);

It's hard to interpret a clause that says "if the given array is subsequently modified..." because no arrays are visible here. To understand it, you need to know that (1) the "given" array is the implicitly generated array that results from a varargs call, and (2) the implementation of lists created by List.of larger than a certain size use an array to store their elements. Given this knowledge that there are two arrays, such a clause would be sensible in that it would require the arrays not to be aliased. However, without providing all this context, I'm skeptical that adding such a clause would provide much value.

s'marks

Reply via email to