shared[0]
has type List<int>
so add performed on shared[0]
should have no effect on shared[1]
.
The fact that shared[0]
is List<int>
is orthogonal to the fact that shared[0]
and shared[1]
are both object references to the same single List<int>
that you created on line 1: var xx = <int>[];
.
Let's go line-by-line:
var xx = <int>[];
- This creates a new empty, resizable
List<int>
object in the program.
- I'm not a Dart user, but from what I can tell this object will live on Dart's GC heap, just like
new List<int>()
in C# or new ArrayList<Integer>()
in Java - and objects that live on the GC heap can have any number of inbound references from elsewhere in the program.
final shared = List.filled(3, xx);
- This creates a second new
List<List<int>>
object, with an initial size of 3
, and each of those 3 elements is a reference to the xx
object passed into filled
.
- The
final
modifier just means that the shared
variable (an object reference) cannot be re-assigned. It does not mean that shared
is an immutable object or in any way read-only, nor does it confer copy-semantics or value-semantics on object-references.
print(shared);
- This prints "
[[], [], []]
" because at-this-point, the xx
list is still empty.
shared[0].add(499);
shared[1].add(599);
- Again, this is the same as doing
shared[2].add(599)
or xx.add(599)
.
print(shared);
- This prints "
[[499, 599], [499, 599], [499, 599]]
".
- Perhaps instead, think of the print output as "
[xx, xx, xx]
".
for (int k = 0; k < shared.length; ++k) for (int j = 0; j < shared[k].length; ++j) print(shared[k][j]);
- This does effectively the same thing as
print(shared)
, except rendering each nested element on its own line, thus hiding the the nested structure of the list.
- If you change the
print
call-site to something like this: print( "k: $k, j: $j == ${shared[k][j]}");
then you get output that's easier to understand:
k: 0, j: 0 == 499
k: 0, j: 1 == 599
k: 1, j: 0 == 499
k: 1, j: 1 == 599
k: 2, j: 0 == 499
k: 2, j: 1 == 599
See for yourself by copying+pasting the code below to Dartpad.dev:
main()
{
var xx = <int>[];
final shared = List.filled(3, xx);
print(shared);
shared[0].add(499);
shared[1].add(599);
print(shared);
print("");
for (int k = 0; k < shared.length; ++k) {
for (int j = 0; j < shared[k].length; ++j) {
print( "k: $k, j: $j == ${shared[k][j]}");
}
}
print("");
var areReferencesToSameObject_xx_0 = identical(xx, shared[0]);
var areReferencesToSameObject_xx_1 = identical(xx, shared[1]);
var areReferencesToSameObject_xx_2 = identical(xx, shared[2]);
var areReferencesToSameObject_1_2 = identical(shared[1], shared[2]);
var areReferencesToSameObject_xx_shared = identical(xx, shared);
print("xx and shared[0] are the same object: $areReferencesToSameObject_xx_0"); // true
print("xx and shared[1] are the same object: $areReferencesToSameObject_xx_1"); // true
print("xx and shared[2] are the same object: $areReferencesToSameObject_xx_2"); // true
print("shared[1] and shared[2] are the same object: $areReferencesToSameObject_1_2"); // true
print("shared and xx are the same object: $areReferencesToSameObject_xx_shared"); // false
}
Gives me this output:
[[], [], []]
[[499, 599], [499, 599], [499, 599]]
k: 0, j: 0 == 499
k: 0, j: 1 == 599
k: 1, j: 0 == 499
k: 1, j: 1 == 599
k: 2, j: 0 == 499
k: 2, j: 1 == 599
xx and shared[0] are the same object: true
xx and shared[1] are the same object: true
xx and shared[2] are the same object: true
shared[1] and shared[2] are the same object: true
shared and xx are the same object: false