Создание объекта внутри цикла

Хорошо ли создать объект внутри цикла. Я указываю на следующий код:

for(some condition){
    SomeClass a = new SomeClass ();
    System.out.println(a);
}

Таким образом, это создаст новый экземпляр SomeClass для каждой итерации. Таким образом, количество экземпляров будет равно числу итераций. И тогда они позже будут собраны GC.

Лучше ли повторно использовать объект SomeClass внутри цикла. Что-то вроде этого:

SomeClass a = null;

for(some condition) {
    a = new SomeClass();
    System.out.println(a);
}

Насколько я понимаю, второй способ лучше, поскольку он только однажды создаст объект SomeClass и будет повторно использовать его на каждой итерации. Но я сомневаюсь. Пожалуйста, подтвердите это, или сообщите мне, где мои основные принципы неверны.

Ответы

Ответ 1

Разница заключается в том, что во втором случае ваша переменная a будет по-прежнему находиться в области действия, когда цикл завершен

кроме этого, они по существу одинаковы, даже с точки зрения сбора мусора.

Строки являются ссылочными типами (хотя и неизменяемыми), и на самом деле неважно, объявляете ли вы новую переменную для них или просто переписываете одну и ту же переменную каждый раз. Вы все равно создаете новую строку каждый раз.

Ответ 2

Вы путаете переменную, которой вы назначаете объект, фактическому экземпляру объекта.

Оба экземпляра кода создают эквивалентное количество объектов. Второй будет содержать один экземпляр в большем объеме, поэтому он будет доступен в течение более длительного времени.

Ответ 3

Оба создают эквивалентное количество строк, потому что String является неизменным. В любое время, когда String присваивается новое значение, создается новый String.

Предположим, вы хотели использовать изменяемый объект в вашем примере.

Вариант 1

for(some condition)
{
    Object o = new Object();
    System.out.println(o);
}

Это создаст новый Object o для каждой итерации цикла.

Вариант 2

Object o;
for(some condition)
{
    o = new Object();
    System.out.println(o);
}

Это создаст новый Object o для каждой итерации цикла.

Даже для изменяемого объекта вы получаете тот же результат в любом случае!

Ответ 4

второй не "лучше".

String a="foo"; повторно использовать литеральную строку из пула строк. То есть, независимо от того, объявляете ли вы a в/вне loop, нет разницы в памяти. Но у них разные возможности. Я думаю, что это еще одна проблема.

даже если с вашей отредактированной версией, с общим SomeClass, это не похоже на то, что вы думали:

второй способ лучше, так как он только однажды создаст объект SomeClass и будет повторно использовать его на каждой итерации.

Он создает новый объект на каждом шаге цикла. a - это просто ссылка на объект. Дело в том, что если созданный вами объект (ы), на который ссылаются другие объекты, GC не будет его собирать и освободить память. Например, старый (< = java1.6) String.subString() метод, он содержит исходную строку как char[], поэтому GC не очистит исходную строку.

Ответ 5

Единственное отличие состоит в том, что во втором случае переменная по-прежнему будет в области действия, когда цикл закончен, нет. объектов, созданных в обоих случаях, равны тем, что строки являются неизменяемыми.

поскольку вы только что отредактировали вопрос, в этом случае новые объекты создаются в памяти на каждой итерации в обоих случаях

Ответ 6

Соблюдайте осторожность, чтобы не путать сам "объект" и "ссылку" на "объект" :

Например, следующий код создает ссылку (null), но объект не создается.

Object a = null;

Следующий код создает оба объекта Object и ссылку на этот объект (ссылка хранится в переменной с именем "a" ):

Object a = new Object();

Следующий код создает новый Object и "переустанавливает" существующую (ссылочную) переменную, чтобы указать на новый объект: если переменная "a" уже содержит другую ссылку, "a" ее пропустит. [но это не значит, что другие переменные могут указывать на старый объект, на который ссылается "a" ].

a = new Object(); // it is the reference 'a' that is 're-used' here not the object...

Каждый раз, когда вы повторно запускаете это утверждение выше в своем цикле; вы действительно создаете новый объект; и вы "перенаправляете" "a" на этот новый объект.

Предыдущая ссылка (т.е. ссылка, содержащаяся в 'a') будет забыта каждый раз; и (при условии, что здесь есть однопоточная программа), что означает, что объект, на который он указал, будет иметь нулевые ссылки, указывающие на него сейчас: это означает, что объект имеет право на сборку мусора. Является ли эта сборка мусора случаем или нет на данный момент - я не знаю, что я боюсь.

Но я бы сказал: нет никакой разницы в ваших примерах кодирования с точки зрения того, когда происходит сборка мусора; независимо от того, был ли "указательный тип" уже определен как "объект" вне цикла или неоднократно переопределен в цикле.

Следующие (бесполезные) примеры могут помочь проиллюстрировать разницу между действиями "Create-an-Object" и "Point-a-Reference", которые код делает за один раз:

// This creates an object ; but we don't hold a reference to it.
    public class TestClass {
    public static void main(String[] args) {
    for (int n=0;n<100;n++) {
        new Object();
    }
    }
    }

И для сравнения:

// This creates a reference ; but no object is created
// This is identical to setting the reference to 'null'.
public class TestClass {
public static void main(String[] args) {
for (int n=0;n<100;n++) {
        Object o;
}
}
}

Ответ 7

в соответствии с моими знаниями - в более крупном приложении (не в этом), но в большей степени лучше использовать static block для создания объекта, потому что статический блок-код выполняется только один раз, когда класс загружается в память. Технически вы можете иметь несколько статических блоков в классе, хотя это не имеет особого смысла

помните: Static block can access only static variables and methods

Ответ 8

Так как тема изменилась совсем немного. Я обновляю:

Если вы действительно хотите повторно использовать созданный объект, вам придется написать этот код самостоятельно. Он мог бы следовать этому принципу:

SomeClass a = new SomeClass();

for(some condition) {
    a.reset();
    //do something with a
}

Где метод SomeClass.reset() обрабатывает все детали (которые зависят от вашего фактического использования объекта).

Ответ 9

все о сфере видимости,

если вы сделаете второй способ:

SomeType someFunction(){
   ...
    SomeClass a = null;

    for(some condition) {
        a = new SomeClass();


           System.out.println(a);
        }
     ...
     return something
    }

объект a будет существовать в памяти до конца someFunction, а для первого метода его жизненный цикл находится в пределах одной итерации цикла