Java的foreach循环是否创建一个新的对象? [英] Does the Java foreach loop create a new object?

查看:998
本文介绍了Java的foreach循环是否创建一个新的对象?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Java会在每次输入foreach循环时创建一个新的对象吗?
我不是在讨论每个迭代,但是如果你有一个多次使用的foreach循环,它是否每次创建对象?

简单示例:(b)

$ $ $ $ $ $ $ $ $ $ $


$ b $ / code $ / pre

只有一个 p 每次执行,或者 c> p 将被实例化为每个 Object o
垃圾收集器是否必须在每次退出时从foreach循环中恢复一个对象?

更具体地说,我写了一些基于Android的游戏代码。它将以每秒给定的速率遍历所有的游戏对象,或者根据具体情况以尽可能快的速度迭代游戏对象。
$ b 这可能是一个过早优化的情况,但如果为或使用明确的循环可以保证我不会从我的循环中获得多余的垃圾回收,那么我就可以把它作为项目的编码标准。



(p>

 public void update()
{
for(GameObject gObj:gameObjects )
{
gObj.update();




$ update()被设计为根据我前面描述的时间进行调用的线程调用。


更新:
我问是否为中的每个 o 创建了一个新的Reference p 对象。不是如果它复制 Objects2 中的对象。那么虚拟机必须创建一个新的引用 p ,然后在outter循环的迭代之间收集这个引用吗?更具体地说,在我的情况下,它是否收集方法调用之间的参考?



更新:
从Matt Ball的回答。
哪个会减少垃圾回收工作?

  //循环运行多次
//可能因为任何原因无数次运行内部的foreach
for(int i = 0; i <1000; i ++)
{
for(Object o:Objects)
{
o.update();


code

$ b $ p $

  Iterator< Object> ITER; 
//循环使其运行多次
//可能因为任何原因无数次运行内部foreach
for(int i = 0; i <1000; i ++ )
{
iter = Objects.iterator(); (iter.hasNext());

while(iter.hasNext());
{
iter.getNext()。update();

$ b

更新:
比较作用域:

pre $ import $ java.util.ArrayList;
import java.util.Iterator;


public class TestLoops
{
public static Iterator< Object>它;
public static ArrayList< Object>对象;

public static void main(String ... args)
{
objects = new ArrayList< Object>();

it = objects.iterator();
it = objects.iterator();

//每当我们开始一个foreach循环时,它是否会创建一个新的引用?
Iterator< Object> newIt1 = objects.iterator();
Iterator< Object> newIt2 = objects.iterator();





产生这个字节码:

  public class TestLoops {
public static java.util.Iterator< java.lang.Object>它;

public static java.util.ArrayList< java.lang.Object>对象;

public TestLoops();

代码:
0:aload_0
1:invokespecial#1 //方法java / lang / Object。< init>:()V
4 :return

public static void main(java.lang.String ...);
代码:
0:new#2 // class java / util / ArrayList
3:dup
4:invokespecial#3 //方法java / util / ArrayList。 ; init>:()V
7:putstatic#4 // Field objects:Ljava / util / ArrayList;
10:getstatic#4 //字段对象:Ljava / util / ArrayList;
13:invokevirtual#5 //方法java / util / ArrayList.iterator :()Ljava / util / Iterator;
16:putstatic#6 //字段:Ljava / util / Iterator;
19:getstatic#4 //字段对象:Ljava / util / ArrayList;
22:invokevirtual#5 //方法java / util / ArrayList.iterator :()Ljava / util / Iterator;
25:putstatic#6 // Field it:Ljava / util / Iterator;
28:getstatic#4 //字段对象:Ljava / util / ArrayList;
31:invokevirtual#5 //方法java / util / ArrayList.iterator :()Ljava / util / Iterator;
34:astore_1
35:getstatic#4 //字段对象:Ljava / util / ArrayList;
38:invokevirtual#5 //方法java / util / ArrayList.iterator :()Ljava / util / Iterator;
41:astore_2
42:return
}


解决方案

没有用for-each循环发生的神奇对象构造。这个语法:

$ p $($)




$ b $ p只是 (Iterator< Object> iter = Objects.iterator(); iter.hasNext()); / / $> ;)
{
Object o = iter.next();
for(Iterator< Object> iter2 = Objects2.iterator(); iter2.hasNext();)
{
Object p = iter2.next();







如果为 Objects 中的每个对象创建了 iter2 引用,

这取决于 Objects2 的来源。它来自 o ?这也取决于 Objects2.iterator()是如何实现的。 Iterable#iterator()预计会返回独立的迭代器,这意味着 Objects2.iterator()几乎肯定会返回每个调用都有一个新的 Iterator 。但是 并没有说明是否遍历 Objects2 中的对象(使用 iter2 )创建其他新对象。



这听起来像是不成熟的优化,总体来说。





哪个可以减少垃圾收集工作?


增强for循环(aka for-each循环)只是语法糖。编译器产生的字节码是相同的。 完整示例:

  package com.stackoverflow; 

import java.util.Iterator;
$ b public class Question14640184
{
public void enhancedForLoop(Iterable< Object> objects1,Iterable< Object> objects2)
{
for(Object o1: objects1)
{
for(Object o2:objects2)
{
// do something
}
}
}
(Iterator< Object> iter1 = objects1.iterator(); iter1.hasNext(););}
public void iteratorForLoop(Iterable< Object> objects1,Iterable< Object> objects2)
{
{
Object o1 = iter1.next();
for(Iterator< Object> iter2 = objects2.iterator(); iter2.hasNext();)
{
Object o2 = iter2.next();



$ b code
$ b

编译:

 ✗javac Question14640184.java 
✗javap -c Question14640184
编译自Question14640184.java
public class com.stackoverflow.Question14640184 extends java.lang.Object {
public com.stackoverflow.Question14640184();
代码:
0:aload_0
1:invokespecial#1; ()方法java / lang / Object。< init>:()V
4:return

public void enhancedForLoop(java.lang.Iterable,java.lang.Iterable) ;
代码:
0:aload_1
1:invokeinterface#2,1; // InterfaceMethod java / lang / Iterable.iterator :()Ljava / util / Iterator;
6:astore_3
7:aload_3
8:invokeinterface#3,1; //接口方法java / util / Iterator.hasNext :()Z
13:ifeq 57
16:aload_3
17:invokeinterface#4,1; // InterfaceMethod java / util / Iterator.next :()Ljava / lang / Object;
22:astore 4
24:aload_2
25:invokeinterface#2,1; // InterfaceMethod java / lang / Iterable.iterator :()Ljava / util / Iterator;
30:astore 5
32:aload 5
34:invokeinterface#3,1; // InterfaceMethod java / util / Iterator.hasNext :()Z
39:ifeq 54
42:aload 5
44:invokeinterface#4,1; // InterfaceMethod java / util / Iterator.next :()Ljava / lang / Object;
49:astore 6
51:goto 32
54:goto 7
57:return

public void iteratorForLoop(java.lang.Iterable,java .lang.Iterable);
代码:
0:aload_1
1:invokeinterface#2,1; // InterfaceMethod java / lang / Iterable.iterator :()Ljava / util / Iterator;
6:astore_3
7:aload_3
8:invokeinterface#3,1; //接口方法java / util / Iterator.hasNext :()Z
13:ifeq 57
16:aload_3
17:invokeinterface#4,1; // InterfaceMethod java / util / Iterator.next :()Ljava / lang / Object;
22:astore 4
24:aload_2
25:invokeinterface#2,1; // InterfaceMethod java / lang / Iterable.iterator :()Ljava / util / Iterator;
30:astore 5
32:aload 5
34:invokeinterface#3,1; // InterfaceMethod java / util / Iterator.hasNext :()Z
39:

就像我所说的, for-each循环 语法糖 a>。


这是我刚才的注意力。


继续,friendo。


Will Java create a new object each time a foreach loop is entered? I'm not talking about each iteration, but if you have a foreach loop that is used multiple times, is it creating objects each time?

Simple Example:

for(Object o : Objects)
{
    for(Object p : Objects2)
    {
    }
}

Would there only be one p per execution, or would p be instantiated for each Object o? Does the Garbage Collector have to recover an object from the foreach loop each time it is exited?

More specifically, I'm writing some Android based game code. It will iterate over all the game objects at a given rate per second, or as fast as it can depending on the circumstances.

It may be a case of premature optimization, but if using an explicit for or while loop can guarantee me that I won't have excess garbage collection from my loops, then I can establish that as a coding standard for the project.

More specifically:

public void update()
{
    for(GameObject gObj : gameObjects)
    {
        gObj.update();
    }
}

With update() being called from a thread designed to make the calls based on the timing I described before.

Update: I am asking if there is a new Reference p being created for each o in Objects. Not if it copies the objects in Objects2. So does the VM have to create a new Reference p, and then does it collect that reference between iterations of the outter loop? And more specifically in my case, does it collect the reference between method calls?

Update: From comments on Matt Ball's answer. Which would create less Garbage Collection work?

//Loop just to have it run a number of times
//Could be running the inner foreach numerous time for any reason
for(int i = 0; i < 1000; i++)
{
    for(Object o : Objects)
    {
        o.update();
    }
}

vs.

Iterator<Object> iter;
//Loop just to have it run a number of times
//Could be running the inner foreach numerous time for any reason
for(int i = 0; i < 1000; i++)
{
    iter = Objects.iterator();

    while(iter.hasNext());
    {
        iter.getNext().update();
    }
}

Update: Comparing scopes:

import java.util.ArrayList;
import java.util.Iterator;


public class TestLoops
{
    public static Iterator<Object> it;
    public static ArrayList<Object> objects;

    public static void main(String... args)
    {
        objects = new ArrayList<Object>();

        it = objects.iterator();
        it = objects.iterator();

            //Every time we start a foreach loop, does it creates a new reference?
        Iterator<Object> newIt1 = objects.iterator();
        Iterator<Object> newIt2 = objects.iterator();       

    }
}

Produces this Bytecode:

public class TestLoops {
public static java.util.Iterator<java.lang.Object> it;

public static java.util.ArrayList<java.lang.Object> objects;

public TestLoops();

    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String...);
    Code:
       0: new           #2                  // class java/util/ArrayList
       3: dup
       4: invokespecial #3                  // Method java/util/ArrayList."<init>":()V
       7: putstatic     #4                  // Field objects:Ljava/util/ArrayList;
      10: getstatic     #4                  // Field objects:Ljava/util/ArrayList;
      13: invokevirtual #5                  // Method java/util/ArrayList.iterator:()Ljava/util/Iterator;
      16: putstatic     #6                  // Field it:Ljava/util/Iterator;
      19: getstatic     #4                  // Field objects:Ljava/util/ArrayList;
      22: invokevirtual #5                  // Method java/util/ArrayList.iterator:()Ljava/util/Iterator;
      25: putstatic     #6                  // Field it:Ljava/util/Iterator;
      28: getstatic     #4                  // Field objects:Ljava/util/ArrayList;
      31: invokevirtual #5                  // Method java/util/ArrayList.iterator:()Ljava/util/Iterator;
      34: astore_1
      35: getstatic     #4                  // Field objects:Ljava/util/ArrayList;
      38: invokevirtual #5                  // Method java/util/ArrayList.iterator:()Ljava/util/Iterator;
      41: astore_2
      42: return
}

解决方案

There is no magical object construction that happens with a for-each loop. This syntax:

for(Object o : Objects)
{
    for(Object p : Objects2)
    {
    }
}

is only shorthand for this:

for(Iterator<Object> iter = Objects.iterator(); iter.hasNext();)
{
    Object o = iter.next();
    for(Iterator<Object> iter2 = Objects2.iterator(); iter2.hasNext();)
    {
        Object p = iter2.next();
    }
}


If would there be an iter2 reference created for every object I had in Objects?

That depends on where Objects2 comes from. Does it come from o? It also depends on how Objects2.iterator() is implemented. Iterable#iterator() is expected to return independent iterators, which means that Objects2.iterator() would almost certainly return a new Iterator for each invocation. But that does not say anything about whether or not iterating through the objects in Objects2 (using iter2) creates other new objects.

This sounds like premature optimization, overall.


Which would create less Garbage Collection work?

Neither. The enhanced for loop (aka for-each loop) is simply syntactic sugar. The bytecode produced by the compiler is identical. Complete example:

package com.stackoverflow;

import java.util.Iterator;

public class Question14640184
{
    public void enhancedForLoop(Iterable<Object> objects1, Iterable<Object> objects2)
    {
        for(Object o1 : objects1)
        {
            for(Object o2 : objects2)
            {
                // do something
            }
        }
    }

    public void iteratorForLoop(Iterable<Object> objects1, Iterable<Object> objects2)
    {
        for(Iterator<Object> iter1 = objects1.iterator(); iter1.hasNext();)
        {
            Object o1 = iter1.next();
            for(Iterator<Object> iter2 = objects2.iterator(); iter2.hasNext();)
            {
                Object o2 = iter2.next();
            }
        }
    }
}

Compile:

✗ javac Question14640184.java
✗ javap -c Question14640184
Compiled from "Question14640184.java"
public class com.stackoverflow.Question14640184 extends java.lang.Object{
public com.stackoverflow.Question14640184();
  Code:
   0:   aload_0
   1:   invokespecial   #1; //Method java/lang/Object."<init>":()V
   4:   return

public void enhancedForLoop(java.lang.Iterable, java.lang.Iterable);
  Code:
   0:   aload_1
   1:   invokeinterface #2,  1; //InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
   6:   astore_3
   7:   aload_3
   8:   invokeinterface #3,  1; //InterfaceMethod java/util/Iterator.hasNext:()Z
   13:  ifeq    57
   16:  aload_3
   17:  invokeinterface #4,  1; //InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
   22:  astore  4
   24:  aload_2
   25:  invokeinterface #2,  1; //InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
   30:  astore  5
   32:  aload   5
   34:  invokeinterface #3,  1; //InterfaceMethod java/util/Iterator.hasNext:()Z
   39:  ifeq    54
   42:  aload   5
   44:  invokeinterface #4,  1; //InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
   49:  astore  6
   51:  goto    32
   54:  goto    7
   57:  return

public void iteratorForLoop(java.lang.Iterable, java.lang.Iterable);
  Code:
   0:   aload_1
   1:   invokeinterface #2,  1; //InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
   6:   astore_3
   7:   aload_3
   8:   invokeinterface #3,  1; //InterfaceMethod java/util/Iterator.hasNext:()Z
   13:  ifeq    57
   16:  aload_3
   17:  invokeinterface #4,  1; //InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
   22:  astore  4
   24:  aload_2
   25:  invokeinterface #2,  1; //InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
   30:  astore  5
   32:  aload   5
   34:  invokeinterface #3,  1; //InterfaceMethod java/util/Iterator.hasNext:()Z
   39:  

So like I said, the for-each loop is only syntactic sugar.

it's something I'm just fixated on.

Move on, friendo.

这篇关于Java的foreach循环是否创建一个新的对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆