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]

Нам не нужно пытаться увеличивать счетчик, это красота для каждого цикла.