l.stream()
создает Stream
, который, вероятно, хранит ссылку на источник List
(я говорю, вероятно, потому что это детали реализации).
В то время, когда вы потребляете Stream
List
уже имеет 4 элемента, поэтому используются 4 элемента.
Изменение ссылки l
на null
не влияет на ссылку, сохраненную в экземпляре Stream
.
если мы не получим исключение, то мы не должны также получать "111" в выводе.
Это было бы верно, только если реализация Stream
создал копию источника List
вместо того, чтобы просто хранить ссылку на оригинал List
.Поскольку это было бы расточительно с точки зрения использования памяти, неудивительно, что это не так.
Глядя на реализацию Collection
stream()
(по крайней мере, в Java 8), я вижу:
default Stream<E> stream() {
return StreamSupport.stream(spliterator(), false);
}
spliterator()
переопределяется на ArrayList
:
public Spliterator<E> spliterator() {
return new ArrayListSpliterator<>(this, 0, -1, 0);
}
и ArrayListSpliterator
сохраняет ссылку на источник List
, как и ожидалось:
static final class ArrayListSpliterator<E> implements Spliterator<E> {
....
private final ArrayList<E> list;
private int index; // current index, modified on advance/split
private int fence; // -1 until used; then one past last index
private int expectedModCount; // initialized when fence set
/** Create new spliterator covering the given range */
ArrayListSpliterator(ArrayList<E> list, int origin, int fence,
int expectedModCount) {
this.list = list; // OK if null unless traversed
this.index = origin;
this.fence = fence;
this.expectedModCount = expectedModCount;
}
....
}