2009-03-04 55 views
39

được điều này cho phép trong java:tạo biến thức bên trong một vòng lặp

for(int i=0;i<5;i++){ 
    final int myFinalVariable = i; 
} 

Từ khóa của câu hỏi của tôi là final. Có được phép thực hiện biến cuối cùng thay đổi với mọi lần chạy vòng lặp không? Tôi đã tự hỏi điều này bởi vì cuối cùng nói rằng bạn không thể thay đổi giá trị của biến (chỉ gọi myFinalVariable = i), nhưng tôi đang xác định lại toàn bộ biến với final int.

Hai biến hoàn toàn khác nhau có cùng tên không - với biến từ lần chạy trước của vòng lặp đã đi xuống đường đến bộ thu gom rác?

Trả lời

73

Có, nó được cho phép. Từ khóa final có nghĩa là bạn không thể thay đổi giá trị của biến số trong phạm vi. Đối với ví dụ vòng lặp của bạn, bạn có thể nghĩ biến biến nằm ngoài phạm vi ở cuối vòng lặp, sau đó quay trở lại phạm vi với một giá trị mới ở đầu vòng lặp. Việc gán cho biến trong vòng lặp sẽ không hoạt động.

11

Bạn đúng, đối với mỗi lần lặp trong vòng lặp, bạn đang tạo một biến mới. Các biến chia sẻ cùng một tên, nhưng điều đó tốt vì chúng không nằm trong cùng phạm vi. Ví dụ tiếp theo sẽ không công việc:

final int myFinalVariable = 0; 
for(int i=0;i<5;i++){ 
    myFinalVariable = i; 
} 
8

Một biến chỉ là một vị trí trên stack. Hãy thử và giữ các biến của bạn với phạm vi nhỏ nhất có thể và cố gắng làm cho chúng trở thành cuối cùng. Tuy nhiên phạm vi và cuối cùng chỉ là những thứ mã nguồn ... từ một thế hệ mã/quan điểm VM, chúng không thực sự quan trọng chút nào.

Trong ví dụ cụ thể của bạn, sử dụng "int" không có rác được tạo. Tuy nhiên nếu nó là đối tượng được tạo ra thì cả hai trường hợp lượng rác và khi rác sẽ đủ điều kiện để dọn dẹp sẽ giống nhau.

Đi đoạn mã sau:

public class X 
{ 
    public static void main(final String[] argv) 
    { 
     foo(); 
     bar(); 
    } 

    private static void foo() 
    { 
     for(int i=0;i<5;i++) 
     { 
      final int myFinalVariable = i; 
     } 
    } 

    private static void bar() 
    { 
     for(int i=0;i<5;i++) 
     { 
      int myFinalVariable = i; 
     } 
    } 
} 

Trình biên dịch tạo ra bytecode giống hệt nhau cho từng phương pháp:

public class X extends java.lang.Object{ 
public X(); 
    Code: 
    0: aload_0 
    1: invokespecial #1; //Method java/lang/Object."<init>":()V 
    4: return 

public static void main(java.lang.String[]); 
    Code: 
    0: invokestatic #2; //Method foo:()V 
    3: invokestatic #3; //Method bar:()V 
    6: return 

private static void foo(); 
    Code: 
    0: iconst_0 
    1: istore_0 
    2: iload_0 
    3: iconst_5 
    4: if_icmpge  15 
    7: iload_0 
    8: istore_1 
    9: iinc 0, 1 
    12: goto 2 
    15: return 

private static void bar(); 
    Code: 
    0: iconst_0 
    1: istore_0 
    2: iload_0 
    3: iconst_5 
    4: if_icmpge  15 
    7: iload_0 
    8: istore_1 
    9: iinc 0, 1 
    12: goto 2 
    15: return 

} 

Thêm một phương pháp khai báo biến bên ngoài vòng cung cấp cho bạn bytecode hơi khác nhau do thứ tự các biến được khai báo). Lưu ý rằng phiên bản này biến không thể được thực hiện cuối cùng. Phiên bản cuối cùng này không phải là cách tốt nhất (biến thức bên trong vòng lặp là tốt nhất nếu bạn có thể làm điều đó):

private static void car() 
{ 
    int myFinalVariable; 

    for(int i=0;i<5;i++) 
    { 
     myFinalVariable = i; 
    } 
} 

private static void car(); 
    Code: 
    0: iconst_0 
    1: istore_1 
    2: iload_1 
    3: iconst_5 
    4: if_icmpge  15 
    7: iload_1 
    8: istore_0 
    9: iinc 1, 1 
    12: goto 2 
    15: return 

} 
2

Như đã trả lời, Vâng, bạn có thể thực sự đánh dấu các biến trong một vòng lặp là 'chính thức' . Đây là hiệu quả của việc làm như vậy (Java 7, Eclipse Indigo, Mac OS X Lion).

for (int i = 0; i < 5; i++) { 

    // With 'final' you cannot assign a new value. 
    final int myFinalVariable = i; // Gets 0, 1, 2, 3, or 4 on each iteration. 
    myFinalVariable = 7; // Compiler error: The final local variable myFinalVariable cannot be assigned. 

    // Without 'final' you can assign a new value. 
    int myNotFinalVariable = i; // Gets 0, 1, 2, 3, or 4 on each iteration. 
    myNotFinalVariable = 7; // Compiler is OK with re-assignment of variable's value. 

} 
2

Biến được khai báo bên trong vòng lặp chỉ có phạm vi cho đến khi thực hiện một vòng lặp. Tuyên bố biến là cuối cùng bên trong vòng lặp làm cho không có sự khác biệt cho biến trong vòng lặp, nhưng nếu chúng ta khai báo biến ngoài vòng lặp với công cụ sửa đổi cuối cùng thì giá trị được gán cho kiểu nguyên thủy hoặc đối tượng được gán cho biến tham chiếu không thể thay đổi .

Trong ví dụ dưới đây, không có vấn đề gì với hai vòng đầu tiên cả hai vòng lặp cung cấp cùng một đầu ra, nhưng vòng thứ ba cung cấp một lỗi thời gian biên dịch.

public class test {

public static void main(String[] args) { 
    for (int i = 0; i < 5; i++) { 
     final int j= i; 
     System.out.println(j); 
    } 
    for (int i = 0; i < 5; i++) { 
     int j= i; 
     System.out.println(j); 
    } 

    final int j; 
    for (int i = 0; i < 5; i++) { 
     j= i; 
     System.out.println(j); 
    } 
} 

}

hãy làm đúng cho tôi nếu tôi đã sai lầm.

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