Java: для каждого цикла и ссылок
Мне интересно, создает ли следующий цикл экземпляр объекта, а не дает мне ссылку на него. Причина в том, что первый пример не выделяет мои объекты массива, но второй делает.
MyObject objects[] = new MyObject[6];
for (MyObject o: objects) {
o = new MyObject();
}
MyObject objects[] = new MyObject[6];
for(int i = 0; i < objects.length; i++) {
objects[i] = new MyObject();
}
Ответы
Ответ 1
Java работает немного иначе, чем многие другие языки. Что o
в первом примере - это просто ссылка на объект.
Когда вы говорите o = new MyObject()
, он создает новый объект типа MyObject и ссылается на этот объект o
, а перед o
ссылается на objects[index]
.
То есть, объекты [index] сами по себе являются просто ссылкой на другой объект в памяти. Поэтому, чтобы установить объекты [index] в новый объект MyObject, вам нужно изменить, на что указывают объекты [index], что может быть сделано только с помощью объектов [index].
Изображение: (мои ужасные навыки рисования: D)
![enter image description here]()
Объяснение:
Это примерно так, как работает управление памятью Java. Не совсем, ни в коем случае, но грубо. У вас есть объекты, которые ссылаются на A1. При доступе массива объектов, вы начинаете с контрольной точкой начала (А1), и двигаться вперед X блоков. Например, ссылка на индекс 1 приведет вас к B1. Затем B1 сообщает вам, что вы ищете объект на A2. A2 сообщает вам, что у него есть поле, расположенное в C2. C2 - целое число, базовый тип данных. Поиск выполнен.
o не ссылается на A1 или B1, но C1 или C2. Когда вы скажете new ...
, он создаст новый объект и поместит туда (например, в слот A3). Это не повлияет на A1 или B1.
Сообщите мне, могу ли я немного разобраться.
Ответ 2
короткий ответ: да, есть что-то вроде копирования.
длинный ответ: цикл Java foreach, который вы опубликовали, представляет собой синтаксический сахар для
MyObject objects[] = new MyObject[6];
Iterator<MyObject> it = objects.iterator();
while (it.hasNext()) {
MyObject o = it.next();
// The previous three lines were from the foreach loop
// Your code inside the foreach loop
o = new MyObject();
}
Как видно из версии desugared, установка ссылки, равная чему-то внутри цикла foreach, не изменяет содержимое массива.
Ответ 3
Я добавил комментарий в каждый пример, чтобы уточнить, что происходит.
Первый пример:
MyObject objects[] = new MyObject[6];
for(MyObject o: objects) {
// Construct a new object of type MyObject and assign a reference to it into
// the iteration variable o. This has no lasting effect, because the foreach
// loop will automatically assign the next value into the iteration variable
// in the the next iteration.
o = new MyObject();
}
Второй пример:
MyObject objects[] = new MyObject[6];
for(int i = 0; i < objects.length; i++) {
// Construct a new object of type MyObject and store a reference to it into the
// i-th slot in array objects[]:
objects[i] = new MyObject();
}
Ответ 4
Первый не выделяет ваши объекты массива, потому что foreach
циклически перебирает элементы в коллекции.
Когда вы вводите этот цикл foreach
, у вас нет элементов в вашей коллекции, это просто пустой массив, инициализированный размером 6, поэтому никакие объекты не будут добавлены в ваш массив.
Также обратите внимание, что даже если бы у вас были элементы в массиве, цикл foreach
не назначал бы поверх них:
o = new MyObject();
в основном означает назначение o
нового экземпляра MyObject
, но o
сам не является частью массива objects
, это только временный контейнер, используемый для итерации по элементам массива, но в этом case, их нет.
Ответ 5
Объекты только "копируются", когда вы явно указываете, что хотите клонировать объект (и этот объект явно реализует функцию клонирования).
Кажется, вы путаете ссылки и имена.
В первом примере, внутри foreach, локальная переменная o
относится к области памяти, в которой хранится некоторый объект из objects
. Когда вы делаете o = new MyObject()
, новый MyObject инициализируется в некоторой другой области памяти, а затем ссылка o
переписывается, чтобы указать на эту новую область памяти.
Во втором примере, написав objects[i] = new MyObject()
, вы говорите, что ссылка objects[i]
должна быть переписана, а не какая-то локальная переменная o
.
Ответ 6
Прежде всего хочу отметить, что массивы с нулевой длиной всегда изменяемы. И внутри цикла foreach
for(MyObject o in objects)
то, что он делает, на каждой итерации работает следующим образом.
o = objects[0] // first iteration
o = objects[1] // 2nd iteration
Но в вашем случае вы назначаете другой объект ссылке o. Не для объектов в массиве. Это просто следующее.
ObjeMyObject objects[] = new MyObject[6];
MyObject o = Object[0];
0 = new MyObject();
Но ваши исходные объекты [0] все еще указывают на нулевой объект.
Ответ 7
Каждый раз, когда вы используете "новый" оператор, JVM создаст новый экземпляр, и он будет назначен операнду левой руки оператора присваивания.
это не имеет значения для каждого цикла или цикла.
In для каждого цикла
для (MyObject O: Object)
O будет создан один раз, только если будет из MyObject, он не будет создан и значения из массива Object будут продолжать копировать в O
как
O = Object[0]
O = Object[1]
O = Object[2]
O = Object[3]
O = Object[4]
O = Object[5]
Нам не нужно пытаться увеличивать счетчик, это красота для каждого цикла.