在循环内创建Object是一个好习惯。我指着以下代码:
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对象,并会在每次迭代中重用它。但我很怀疑。请确认一下,或者让我知道我的基本面不正确的地方。
答案 0 :(得分:13)
不同之处在于,在第二种情况下,当循环结束时,您的a
变量仍然在范围内
字符串是引用类型(尽管是不可变的),无论是为它们声明一个新变量还是每次都覆盖相同的变量,它并不重要。你每次都在创建一个全新的字符串。
答案 1 :(得分:5)
两者都创建了等量的字符串,因为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。
即使对于一个可变对象,你也可以得到相同的结果!
答案 2 :(得分:5)
小心不要将'Object'本身和'Reference'混淆为'Object':
例如,以下代码创建一个(null)引用,但不创建任何对象。
Object a = null;
以下代码创建一个Object和对该对象的引用(引用保存在名为'a'的变量中):
Object a = new Object();
以下代码创建新的Object并'repoints'一个现有的(引用)变量以指向新的Object:如果变量'a'已经拥有另一个引用,'a'就会忘记它。 [但这并不意味着其他变量仍可能指向'a'引用的旧对象。
a = new Object(); // it is the reference 'a' that is 're-used' here not the object...
每次在循环中重新运行上面的语句;你确实在创造一个新的对象;你正在'重新指向''到那个新对象。
以前的参考文献(即'a'中的参考文献)每次都会被遗忘;并且(假设我们这里有一个单线程程序)这意味着它指向的对象现在将有零引用指向它:这意味着该对象符合垃圾收集的条件。这个垃圾收集是否在此时发生 - 我不知道我害怕。
但我会说:在垃圾收集发生的时候,你的编码示例没有区别;是否'指针类型'已经被定义为循环外的'对象',或者在循环中重复定义。
以下(无用的)示例可能有助于说明代码一次性执行的“创建对象”和“点对象”操作之间的区别:
// 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;
}
}
}
答案 3 :(得分:3)
您将对象指定的变量混淆到实际的对象实例。
两个代码示例都创建了等量的对象。第二个实例将使一个实例保持在更大的范围内,因此可以使用更长的时间。
答案 4 :(得分:3)
第二个不是“更好”。
String a="foo";
重用字符串池中的文字字符串。也就是说,无论您在a
之内/之外声明loop
,内存方面都没有区别。但它们的范围不同。我认为这是另一个问题。
即使使用您的编辑版本,使用常规SomeClass
,也不会像您想的那样:
第二种方式更好,因为这只会创建一次SomeClass对象,并会在每次迭代中重复使用它。
它在每个循环步骤中创建新对象。 a
只是对象的引用。关键是,如果您创建的对象由其他对象引用,GC将不会收集它,并释放内存。例如,旧的(&lt; = java1.6)String.subString()方法,它将原始String保存为char[]
,因此GC不会清除原始String。
答案 5 :(得分:3)
唯一的区别是,在第二种情况下,当循环结束时变量仍然在范围内,否。在两种情况下创建的对象都是相同的,因为字符串是不可变的
因为你刚刚编辑了问题,在这种情况下,在两种情况下每次迭代都会在内存中创建新对象
答案 6 :(得分:3)
根据我的知识 - 在更大的应用程序中(不在此),但更大的是更好地使用static block
来创建对象 - 因为静态块代码只在类加载到内存时执行一次。从技术上讲,你可以在一个类中拥有多个静态块,尽管它没有多大意义
记住:Static block can access only static variables and methods
答案 7 :(得分:2)
由于主题发生了很大变化。我更新:
如果你真的想重用一次创建对象,你必须自己编写代码。它可以遵循这一原则:
SomeClass a = new SomeClass();
for(some condition) {
a.reset();
//do something with a
}
SomeClass.reset()
方法处理所有细节(取决于您对象的实际使用情况)。
答案 8 :(得分:2)
一切都与范围有关,
如果你采取第二种方式:
SomeType someFunction(){
...
SomeClass a = null;
for(some condition) {
a = new SomeClass();
System.out.println(a);
}
...
return something
}
对象a将存在于内存中直到someFunction
结束,而对于第一种方法,它的生命周期是在循环的单次迭代中