루프

2009-03-04 6 views
39

안에 최종 변수를 만드는이 자바에 허용 : 내 질문의루프

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

키워드는 final입니다. 루프 실행마다 변경되는 최종 변수를 허용합니까? 나는 final이 변수의 값을 변경할 수 없다고 (myFinalVariable = i 만 호출한다), 그러나 나는 전체 변수를 final int으로 재정의하고 있기 때문에 이것을 궁금해하고 있었다.

두 개의 완전히 다른 변수가 동일한 이름을 가진 것입니까? 이전 루프 실행 변수가 이미 가비지 수집기로 향하고 있습니까?

답변

73

예, 허용됩니다. final 키워드는 범위 내에서 변수의 값을 변경할 수 없다는 것을 의미합니다. 루프 예제의 경우 루프의 맨 아래에있는 변수가 범위를 벗어나고 루프의 맨 위에 새로운 값이있는 범위로 되돌아 오는 것으로 생각할 수 있습니다. 루프 내에서 변수에 지정하면 작동하지 않습니다.

11

네가 맞다. 루프의 각 반복마다 새로운 변수가 생성된다. 변수는 같은 이름을 공유하지만 동일한 범위에 있지 않기 때문에 괜찮습니다.

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

변수는 스택에 단지 위치 : 다음 예는하지 작업을 것이다. 가능한 한 작은 범위로 변수를 시도하고 유지하고 최종적으로 만드십시오. 그러나 스코프와 파이널은 소스 코드 일뿐입니다 ... 코드 생성/VM 관점에서 보면 전혀 문제가되지 않습니다.

특정 예에서 "int"를 사용하면 가비지가 생성되지 않습니다. 그러나 그것이 생성되는 객체라면 두 경우 모두 쓰레기의 양과 쓰레기가 정리 대상이되는 시점은 동일합니다.

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 

} 

루프 외부 변수로 인해 당신에게 약간 다른 바이트 코드를 부여 선언 다른 방법을 추가 :

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

컴파일러는 각 방법에 대한 동일한 바이트 코드를 생성합니다

다음 코드를 가지고 변수가 선언 된 순서). 이 버전의 변수는 final로 만들 수 없습니다. 이 마지막 버전은 가장 좋은 방법은 아닙니다 (당신이 그것을 할 수 있다면 루프 내 마지막 변수는 최고입니다) : 대답으로

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

은, 예, 당신은 루프에서 변수를 표시 실제로 할 수있다 '최종' . 그렇게하는 것의 효과는 다음과 같습니다 (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

변수는 루프의 단일 실행까지 범위를 가지고있다.

변수를 루프 내부에서 final로 선언하면 변수가 루프 측면에서 차이가 없지만 최종 수정자를 사용하여 루프 외부에서 변수를 선언하면 원시 변수 유형에 지정된 값이나 참조 변수에 할당 된 값 변경할 수 없습니다.

아래의 예제에서 첫 번째 두 루프에서는 두 루프가 동일한 출력을 제공하지만 세 번째 루프에서는 컴파일 타임 오류가 발생합니다.

공용 클래스 테스트 {

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

}

만약 내가 잘못 정정 해줘 마십시오.