6

Java は foreach ループに入るたびに新しいオブジェクトを作成しますか? 各繰り返しについて話しているわけではありませんが、複数回使用される foreach ループがある場合、毎回オブジェクトを作成していますか?

簡単な例:

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

p実行ごとに 1 つしかありませんか、それともpそれぞれに対してインスタンス化されますObject oか? ガベージ コレクターは、終了するたびに foreach ループからオブジェクトを回復する必要がありますか?

具体的には、Android ベースのゲーム コードを書いています。すべてのゲーム オブジェクトを毎秒指定された速度で、または状況に応じてできるだけ速く反復処理します。

時期尚早の最適化のケースかもしれませんが、明示的なfororwhileループを使用することで、ループから余分なガベージ コレクションが発生しないことが保証される場合は、それをプロジェクトのコーディング標準として確立できます。

すなわち:

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

前述update()のタイミングに基づいて呼び出しを行うように設計されたスレッドから呼び出されます。

更新:pのそれぞれに対して新しい参照が作成されているoか どうかを尋ねていObjectsます。のオブジェクトをコピーする場合ではありませんObjects2。では、VM は新しい Reference を作成する必要がpあり、外側のループの反復間でその参照を収集しますか? より具体的には、私の場合、メソッド呼び出し間の参照を収集しますか?

更新: Matt Ball の回答に関するコメントから。ガベージ コレクションの作業が少なくて済むのはどれですか?

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

対。

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

更新: スコープの比較:

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

    }
}

このバイトコードを生成します:

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
}
4

2 に答える 2

7

for-each ループで発生する魔法のオブジェクト構築はありません。この構文:

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

はこれの省略形に過ぎません:

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

iter2私が持っていたすべてのオブジェクトに対して作成された参照があるとしObjectsたら?

それはどこObjects2から来たかによります。由来oですか?また、実装方法によっても異なりますObjects2.iterator()Iterable#iterator()は独立したイテレータを返すことが期待されています。つまり、呼び出しごとObjects2.iterator()にほぼ確実に新しいイテレータが返されます。Iteratorしかし、 ( を使用して) 内のオブジェクトを反復処理することで、他の新しいオブジェクトが作成されるかどうかについては何も述べていません。Objects2iter2

全体として、これは時期尚早の最適化のように思えます。


ガベージ コレクションの作業が少なくて済むのはどれですか?

ない。強化された for ループ (別名 for-each ループ) は、単なるシンタックス シュガーです。コンパイラによって生成されるバイトコードは同じです。完全な例:

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

コンパイル:

✗ 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:  

私が言ったように、for-each ループは単なる 構文の砂糖です。

それは私が固執しているものです。

行こう、友よ。

于 2013-02-01T05:17:45.330 に答える