简体   繁体   English

在循环内创建一个Object

[英]Creating an Object inside a loop

Is it a good practice to create an Object inside a loop. 在循环内创建Object是一个好习惯。 I am pointing towards the following code: 我指向以下代码:

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

So this would create a new instance of SomeClass for each iteration. 因此,这将为每次迭代创建一个SomeClass的新实例。 So number of instances will be equal to number of iterations. 因此,实例数将等于迭代次数。 And then these will later be collected by GC. 然后这些将由GC收集。

Is it better to reuse a SomeClass object inside the loop. 在循环中重用SomeClass对象是否更好? Something like this: 像这样的东西:

SomeClass a = null;

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

As far as I understand this, the second way is better as this will just create the SomeClass object once and will reuse it in every iteration. 据我所知,第二种方式更好,因为这将只创建一次SomeClass对象,并将在每次迭代中重用它。 But I am doubtful. 但我很怀疑。 Please confirm this, or let me know where my fundamentals are incorrect. 请确认一下,或者让我知道我的基本面不正确的地方。

The difference is that in your second case, your a variable will still be in scope when the loop is over 所不同的是,在你的第二个情况下,你的a变量仍然是在范围上,当循环结束

other than that, they're essentially the same, even from a garbage collection point of view. 除此之外,它们基本上是相同的,即使从垃圾收集的角度来看也是如此。

Strings are reference types(albeit immutable ones), and it doesn't really matter whether you declare a new variable for them or just overwrite the same variable each time. 字符串是引用类型(尽管是不可变的),无论是为它们声明一个新变量还是每次都覆盖相同的变量,它并不重要。 You're still creating a brand new string every time. 你每次都在创造一个全新的字符串。

Both create an equivalent amount of strings because String is immutable. 两者都创建了等量的字符串,因为String是不可变的。 Anytime a String is assigned a new value, a new String is created. 无论何时为String分配新值,都会创建一个新的String

Let's assume you meant to use a mutable object in your example. 我们假设你打算在你的例子中使用一个可变对象。

Option 1 选项1

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

This will create a new Object o for each iteration of the loop. 这将为循环的每次迭代创建一个新的Object o。

Option 2 选项2

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

This will create a new Object o for each iteration of the loop. 这将为循环的每次迭代创建一个新的Object o。

Even for a mutable object, you get the same result either way! 即使对于一个可变对象,你也可以得到相同的结果!

Be careful not confuse the 'Object' itself and a 'Reference' to an 'Object': 注意不要将'Object'本身和'Reference'混淆为'Object':

For instance the following code creates a (null) Reference, but no object is created. 例如,以下代码创建(null)引用,但不创建任何对象。

Object a = null;

The following code create boths an Object AND a reference to that object (the reference is held in a variable called 'a'): 以下代码创建了一个Object和对该对象的引用(引用保存在一个名为'a'的变量中):

Object a = new Object();

The following code creates new Object and 'repoints' an existing (reference) variable to point to the new Object: if the variable 'a' already held another reference, 'a' forgots it. 下面的代码创建新的Object并'repoints'一个现有的(引用)变量指向新的Object:如果变量'a'已经拥有另一个引用,'a'就会忘记它。 [but that doesn't mean other variables may still point to the old object referenced by 'a']. [但这并不意味着其他变量仍可能指向'a'引用的旧对象]。

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

Everytime you re-run the that statement above in your loop; 每次在循环中重新运行上面的语句; you are indeed creating a new object ; 你确实在创造一个新的对象; and you are 're-pointing' 'a' to that new object. 而你正在'重新指向''到那个新对象。

The previous reference (ie reference held in 'a') will be forgotten each time; 以前的参考文献(即'a'中的参考文献)每次都会被遗忘; and (assuming we have a single-threaded program here) that means the object it pointed to will have zero references pointing at it now: which means the object is eligible for Garbage Collection. 并且(假设我们这里有一个单线程程序)这意味着它指向的对象现在将有零引用指向它:这意味着该对象符合垃圾收集的条件。 Whether this Garbage collection happens or not at this point in time - I don't know I'm afraid. 这个垃圾收集是否发生在这个时间点 - 我不知道我害怕。

But I would say : that there is no difference in your coding examples in terms of when Garbage Collection happens; 但我会说:在垃圾收集发生的时候,你的编码例子没有区别; whether or not the 'pointer-type' is already defined as an 'Object' outside of the loop, or repeatedly redefined within the loop. 是否已将“指针类型”定义为循环外的“对象”,或者在循环内重复定义。

The following (useless) examples might help illustrate the difference between the 'Create-an-Object' and 'Point-a-Reference' actions that the code does in one go: 以下(无用的)示例可能有助于说明代码执行的“创建对象”和“点对象”操作之间的区别:

// 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();
    }
    }
    }

And to contrast: 与之形成对比:

// 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;
}
}
}

You are confusing the variable you assign an object to, to the actual object instance. 您将分配对象的变量混淆到实际的对象实例。

Both code samples create the equivalent amount of objects. 两个代码示例都创建了等量的对象。 The second one will keep one instance in larger scope, thus it will be available for a longer time. 第二个实例将使一个实例保持在更大的范围内,因此可以使用更长的时间。

the 2nd is not "better". 第二个不是“更好”。

String a="foo"; reuse a literal string from string pool. 重用字符串池中的文字字符串。 That is, no matter you declare the a in/outside the loop , there is no difference in terms of memory. 也就是说,无论你在loop /外部声明a ,内存方面都没有区别。 But they have different scope. 但它们的范围不同。 I think it is another issue. 我认为这是另一个问题。

even if with your edited version, with general SomeClass , it is not like what you thought: 即使你的编辑版本与一般的SomeClass ,它也不像你想的那样:

the second way is better as this will just create the SomeClass object once and will reuse it in every iteration . 第二种方式更好,因为这将只创建一次SomeClass对象,并将在每次迭代中重用它。

It creates new object in each loop step. 它在每个循环步骤中创建新对象。 a is just a reference to the object. a只是对象的引用。 The point is, if the object(s) you created referenced by other objects, GC will not collect it, and release the memory. 关键是,如果您创建的对象由其他对象引用,GC将不会收集它,并释放内存。 For example, the old (<=java1.6) String.subString() method, it holds the original String as char[] , so GC won't clean the original String. 例如,旧的(<= java1.6)String.subString()方法,它将原始String保存为char[] ,因此GC不会清除原始String。

The only difference is that in the second case, variable will still be in scope when the loop is over ,no. 唯一的区别是,在第二种情况下,当循环结束时变量仍然在范围内,否。 of objects that are created in both the cases are equal as Strings are immutable 在两种情况下创建的对象都是相同的,因为字符串是不可变的

as you have just edit the question still in this case new Objects are created in the memory at each iteration in both the cases 正如你刚刚编辑问题一样,在这种情况下,每次迭代都会在内存中创建新对象

according to my knowledge - in bigger application (not in this) but in bigger is better to use static block for object creation - because static block code is executed only once when class is loaded into memory. 根据我的知识 - 在更大的应用程序(不在此)中,但更大的是更好地使用static block来创建对象 - 因为静态块代码只在类加载到内存时执行一次。 Technically, you can can have multiple static blocks in a class, although it doesn't make much sense 从技术上讲,你可以在一个类中拥有多个静态块,尽管它没有多大意义

remember: Static block can access only static variables and methods 记住: Static block can access only static variables and methods

Since the topic has changed quite a bit. 由于主题已经发生了很大的变化。 I update: 我更新:

If you really want to reuse the once create object you will have to write that code yourself. 如果您真的想重用一次创建对象,则必须自己编写该代码。 It could follow this principle: 它可以遵循这个原则:

SomeClass a = new SomeClass();

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

Where the SomeClass.reset() method handles all the details (which are dependant on your actual usage of the object). SomeClass.reset()方法处理所有细节(取决于您对象的实际用法)。

it is all about scope, 这完全是关于范围,

if you do your second way: 如果你做第二种方式:

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

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


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

object a will exist in memory till end of someFunction while for first method, its lifecycle is within single iteration of loop 对象a将存在于内存中直到someFunction结束,而对于第一种方法,它的生命周期在循环的单次迭代中

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM