[External] : Re: Q: List.of(E... elements) specification with regards to underlying array updates

Stuart Marks stuart.marks at oracle.com
Tue Sep 2 17:54:14 UTC 2025



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 <eirbjo at gmail.com> 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



More information about the core-libs-dev mailing list