2010-12-30 1 views
7
String[] strs = new String[] { "1", "2", ... , "6" }; 

for (String s : strs) { 
    System.out.println(s); 
} 

これはJavaの内部構造についての質問です。Javaはどのようにして配列を反復するのかを知ります

上記のコードサンプルでは、​​配列の長さをforeachループがどのように把握していますか?配列は実際には内部的にオブジェクトなのですか、フロントエンドのプログラマがアクセスできないsizeofのようなものを使用していますか?

私はちょっと愚かなものを逃している気がしますが、私はそれもクールかもしれないと思います。 :-)

+0

[各ループのJavaはどのように動作しますか?](http://stackoverflow.com/questions/85190/how-does-the-java-for-each-loop-work) –

+1

+1興味深い質問ではなく、全く重複していません。 –

+0

私はすでに反復可能であることを知っていますが、イテレータは反復をいつ止めるべきかを知っていますか? – SapphireSun

答えて

11

public class ArrayIterator 
{ 
    public static void main(String[] argv) 
    { 
     String[] strs = new String[] { "1", "2", "3", "4", "5" }; 
     enhancedPrint(strs); 
     normalPrint(strs); 
    } 

    public static void enhancedPrint(String[] strs) 
    { 
     for (String s : strs) 
     { 
      System.out.println(s); 
     } 
    } 

    public static void normalPrint(String[] strs) 
    { 
     String[] localArray = strs; 
     int len = localArray.length; 
     for (int i = 0; i < len; i++) 
     { 
      String s = localArray[i]; 
      System.out.println(s); 
     } 
    } 
} 

これは、反復機能のために解体(javap -c ArrayIterator)バイトコードです:

強化プリント:

public static void enhancedPrint(java.lang.String[]); 
    Code: 
    0: aload_0 
    1: astore_1 
    2: aload_1 
    3: arraylength 
    4: istore_2 
    5: iconst_0 
    6: istore_3 
    7: iload_3 
    8: iload_2 
    9: if_icmpge 31 
    12: aload_1 
    13: iload_3 
    14: aaload 
    15: astore 4 
    17: getstatic #10; //Field java/lang/System.out:Ljava/io/PrintStream; 
    20: aload 4 
    22: invokevirtual #11; //Method java/io/PrintStream.println:(Ljava/lang/String;)V 
    25: iinc 3, 1 
    28: goto 7 
    31: return 

ループの通常:あなたが見ることができるように

public static void normalPrint(java.lang.String[]); 
    Code: 
    0: aload_0 
    1: astore_1 
    2: aload_1 
    3: arraylength 
    4: istore_2 
    5: iconst_0 
    6: istore_3 
    7: iload_3 
    8: iload_2 
    9: if_icmpge 31 
    12: aload_1 
    13: iload_3 
    14: aaload 
    15: astore 4 
    17: getstatic #10; //Field java/lang/System.out:Ljava/io/PrintStream; 
    20: aload 4 
    22: invokevirtual #11; //Method java/io/PrintStream.println:(Ljava/lang/String;)V 
    25: iinc 3, 1 
    28: goto 7 
    31: return 

、両方の場合において、コンパイラは、配列の長さ(strs.length)をロードされ、それに対してループ。配列の場合、for-eachループの拡張は、(Iteratorを使用するObjectの場合ではなく)配列の長さに対してループするための構文的砂糖であることがわかります。私はそれがはるかに少ない慣用的であるように、それは拡張forループと同じバイトコードを持っていることをループのための「通常」を編集した


。すべての目的と目的で、通常のforループバージョンは、各ループに対して拡張されたものをコンパイルするときにコンパイラが生成するものです。

+0

Whoa!どうもありがとう! – SapphireSun

3

はい、C++ sizeofオペレータに似て何かがある - それはlengthインスタンス変数ですlengthフィールド(配列ではなく、バイト単位のサイズの要素の数を与えます。)常に配列のパブリックメンバであるため、Javaプログラマはアクセスできます。

はい、配列はobjectsであり、内部だけではありません。

(にリンクorg.life.java questionで説明したようにもっと広く、forループ構文は動作します。しかし、それはあなたが求めていたものはかなりではありません。)私は、次のコードをコンパイル

関連する問題