Создание объекта внутри цикла
Хорошо ли создать объект внутри цикла. Я указываю на следующий код:
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
, а для первого метода его жизненный цикл находится в пределах одной итерации цикла