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

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

Đây là câu hỏi về nội bộ java.Làm thế nào để Java biết cách làm đổi một mảng

Trong mẫu mã ở trên, vòng lặp foreach tìm ra chuỗi dài bao nhiêu? Các mảng thực sự là các đối tượng trong nội bộ hay là sử dụng các công cụ như sizeof không thể truy cập được đối với các lập trình viên giao diện người dùng?

Tôi có cảm giác mình chỉ thiếu một thứ gì đó ngu ngốc, nhưng tôi thấy nó cũng có thể rất tuyệt. :-)

+0

bản sao có thể có của [Làm thế nào để Java cho mỗi vòng lặp hoạt động?] (Http://stackoverflow.com/questions/85190/how-does-the-java-for-each-loop-work) –

+1

+1 thú vị câu hỏi và hoàn toàn không trùng lặp. –

+0

Không hoàn toàn. Tôi đã biết nó là iterable, nhưng làm thế nào để iterator biết khi nào dừng lặp lại? – SapphireSun

Trả lời

11

tôi biên soạn đoạn mã sau:

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

Đây là tháo rời (javap -c ArrayIterator) bytecode cho các chức năng iterating:

việc tăng cường in:

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 

Một bình thường đối với vòng lặp:

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 

Như bạn có thể thấy, trong cả hai trường hợp, trình biên dịch đang tải chiều dài mảng (strs.length) và vòng lặp chống lại nó. Chúng ta thấy rằng vòng lặp for-each được tăng cường, trong trường hợp của một Array là cú pháp đường để lặp lại với chiều dài của mảng (chứ không phải trong trường hợp của Object khi nó sử dụng một Iterator).


Tôi đã chỉnh sửa vòng lặp 'bình thường' sao cho nó ít thành ngữ hơn, nhưng nó có cùng mã byte như tăng cường cho vòng lặp. Đối với tất cả các ý định và mục đích, bình thường cho phiên bản vòng lặp là những gì trình biên dịch tạo ra khi nó biên dịch tăng cường cho mỗi vòng lặp.

+0

Whoa! Cảm ơn rất nhiều! – SapphireSun

3

Vâng, có cái gì đó giống như các nhà điều hành C++ sizeof - đó là biến length dụ Trường length (mà cho biết số của các yếu tố trong mảng, không phải là kích thước tính bằng byte.) luôn là một thành viên công khai của mảng, vì vậy nó có thể truy cập được tới các lập trình viên Java.

Và có, mảng là objects và không chỉ nội bộ.

(Nói rộng hơn, cú pháp for vòng lặp hoạt động như mô tả trong question rằng org.life.java liên quan đến, nhưng đó không phải là khá những gì bạn đã yêu cầu.)

Các vấn đề liên quan