在循环内创建一个Object

时间:2014-02-18 17:06:40

标签: java oop loops object

在循环内创建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对象,并会在每次迭代中重用它。但我很怀疑。请确认一下,或者让我知道我的基本面不正确的地方。

9 个答案:

答案 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结束,而对于第一种方法,它的生命周期是在循环的单次迭代中