简体   繁体   English

Java:在循环中实例化变量:风格好还是坏?

[英]Java: instantiate variables in loop: good or bad style?

Ive got one simple question.我有一个简单的问题。 Normally I write code like this:通常我会写这样的代码:

String myString = "hello";

for (int i=0, i<10; i++)
{
  myString = "hello again";
}

Because I think the following would not be good style cause it would create too many unnecessary objects.因为我认为以下不是好的风格,因为它会创建太多不必要的对象。

for (int i=0, i<10; i++)
{
  String myString = "hello again";
}

Is this even correct?这甚至正确吗? Or is this just the case when Ive got an explicit object like an object from a class I created?或者这只是当我从我创建的类中获得一个显式对象时的情况? What if it was a boolean or an int?如果它是一个布尔值或一个整数呢? What is better coding style?什么是更好的编码风格? Instantiate it once before the loop and use it in the loop or instantiate it every time in the loop again?在循环之前实例化一次并在循环中使用它还是每次在循环中再次实例化它? And why?为什么? Because the program is faster or less storage is used or...?因为程序更快或使用更少的存储空间还是...?

Some one told me, if it was a boolean I should instantiate it directly in the loop.有人告诉我,如果它是一个布尔值,我应该直接在循环中实例化它。 He said it would not make a difference for the heap and it would be more clear that the variable belongs inside the loop.他说这不会对堆产生影响,而且变量属于循环内部会更清楚。 So what is correct?那么什么是正确的呢?

Thanks for an answer!感谢您的回答! :-) :-)

==== ====

Thanks for all your answers!感谢您的所有回答!

In conclusion: it is preferable to declare an object inside the smallest scope possible.总之:最好在尽可能小的范围内声明一个对象。 There are no performance improvements by declaring and instantiating objects outside the loop, even if in every looping the object is reinstantiated.即使在每次循环中重新实例化对象,在循环外声明和实例化对象也不会提高性能。

No, the latter code isn't actually valid.不,后一个代码实际上无效。 It would be with braces though:不过它会带大括号:

for (int i=0; i<10; i++)
{
    String myString = "hello again";
}

(Basically you can't use a variable declaration as a single-statement body for an if statement, a loop etc.) (基本上,您不能将变量声明用作if语句、循环等的单语句体。)

It would be pointless, but valid - and preferable to the first version, IMO.这将毫无意义,但有效 - 并且比第一个版本 IMO更可取 It takes no more memory, but it's generally a good idea to give your local variables the narrowest scope you can, declaring as late as you can, ideally initializing at the same point.它不需要更多的内存,但通常给你的局部变量尽可能窄的范围是一个好主意,尽可能晚地声明,最好在同一点初始化。 It makes it clearer where each variable can be used.它使可以使用每个变量的位置更加清晰。

Of course, if you need to refer to the variable outside the loop (before or afterwards) then you'll need to declare it outside the loop too.当然,如果您需要在循环外(之前或之后)引用变量,那么您也需要在循环外声明它。

You need to differentiate between variables and objects when you consider efficiency.考虑效率时需要区分变量对象 The above code uses at most one object - the String object referred to by the literal "hello again".上面的代码最多使用一个对象——字面量“hello again”引用的 String 对象。

As Binyamin Sharet mentioned, you generally want to declare a variable within the smallest scope possible.正如 Binyamin Sharet 提到的,您通常希望在尽可能小的范围内声明一个变量。 In your specific examples, the second one is generally preferable unless you need access to the variable outside your loop.在您的具体示例中,第二个通常更可取,除非您需要访问循环外的变量。

However, under certain conditions this can have performance implications--namely, if you are instantiating the same object over and over again.但是,在某些情况下,这可能会影响性能——即,如果您一遍又一遍地实例化同一个对象。 In your particular example, you benefit from Java's automatic pooling of String literals.在您的特定示例中,您可以从 Java 的字符串文字自动池中受益。 But suppose you were actually creating a new instance of the same object on every iteration of the loop, and this loop was being executed hundreds or thousands of times:但是假设您实际上在循环的每次迭代中创建了同一个对象的新实例,并且这个循环被执行了数百或数千次:

for (int i=0, i<1000; i++)
{
  String myString = new String("hello again"); // 1000 Strings are created--one on every iteration
  ...
}

If your loop is looping hundreds or thousands of times but it just so happens that you're instantiating the same object over and over again, instantiating it inside the loop is going to result in a lot of unnecessary garbage collection, because you create and throw away a new object on every iteration.如果你的循环循环了成百上千次,但碰巧你一遍又一遍地实例化同一个对象,在循环内实例化它会导致很多不必要的垃圾收集,因为你创建并抛出每次迭代都会删除一个新对象。 In that case, you would be better off declaring and instantiating the variable once outside of the loop:在这种情况下,最好在循环之外声明和实例化变量:

String myString = new String("hello again"); // only one String is created

for (int i=0, i<1000; i++)
{
  ...
}

And, to come full circle, you can manually limit the scope by adding extra braces around the relevant section of code:而且,为了完整循环,您可以通过在相关代码部分周围添加额外的大括号来手动限制范围:

{ // Limit the scope
  String myString = new String("hello again");

  for (int i=0, i<1000; i++)
  {
    ...
  }
}

似乎您的意思是declare ,而不是instantiate ,一般来说,您应该在所需的最小范围内声明一个变量(在这种情况下 - 在循环中)。

如果您打算在 for 循环之外使用该变量,则将其声明在外面,否则最好将范围保持在最小

The problem with the second is you create object and someone (the GC) has to clean them, of course for a 10 iteration it is unimportant.第二个的问题是你创建了对象并且有人(GC)必须清理它们,当然对于 10 次迭代来说这并不重要。

BTW in your specific example I would have wrote顺便说一句,在您的具体示例中,我会写

    String myString = null; 
    final String HELLO_AGAIN="hello again";
    for (int i=0; i<10; i++)
      myString = HELLO_AGAIN;

除非值被改变,你绝对应该在循环之外实例化。

The problem here is that String is an immutable object: you cannot change the value of a string, only you can create new String objects.这里的问题是 String 是一个不可变对象:您不能更改字符串的值,只能创建新的 String 对象。 Either way, if your goal is to assign a variable a new object instance, then limit your scope and declare it inside the body of your loop.无论哪种方式,如果您的目标是为一个变量分配一个新的对象实例,那么请限制您的范围并在您的循环体内声明它。

If your object is mutable, then it would be reasonable to reuse the object in every next iteration of the loop, and just change those attributes you need.如果您的对象是可变的,那么在循环的每次下一次迭代中重用该对象是合理的,并且只需更改您需要的那些属性。 This concept is used to run the same query multiple times, but with different parameters, you use a PreparedStatement.这个概念用于多次运行相同的查询,但使用不同的参数,您使用 PreparedStatement。

In the extreme case, you would even maintain pools of objects which can be shared within the whole application.在极端情况下,您甚至会维护可以在整个应用程序中共享的对象池。 You create additional objects as you run out of resources, you shrink if you detect a reasonable amount of non-use.当您耗尽资源时,您会创建其他对象,如果您检测到合理数量的未使用,则会缩小。 This concept is used to maintain a Connection Pool.这个概念用于维护连接池。

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

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