인프런 커뮤니티 질문&답변

인프린님의 프로필 이미지
인프린

작성한 질문수

김영한의 실전 자바 - 중급 1편

지역 클래스 - 지역 변수 캡처3

지역 클래스 지역 변수 캡쳐 질문

작성

·

165

0

안녕하세요.

자바의 설계상 동기화 등의 문제로 지역 클래스가 생성되 때 지역 변수의 값을 캡쳐하기 때문에 값을 변경하면 컴파일 에러가 난다는 설명에서 문의드릴 게 있습니다.

설명해주신 예제로 확인하면 순서가

1.process() 호출 -> 스택 프레임 생성

2. 해당 메서드 바디의 코드 실행

3. LocalPrinter() 객체 생성

인데, 여기서 3번 LocalPrinter() 객체가 생성이 될 때 지역 변수를 쓰는 게 있다면 그 지역 변수를 LocalPrinter() 객체 내부로 변수를 캡쳐해서 활용한다는 것이잖아요 ?

 

그러면 설명해주신 것과 같이 객체 생성 이후에 값을 변경하려고 하면 동기화 문제가 발생할 수 있어서 자바에서 그렇게 설계를 안했다는 건 이해를 하겠는데, 객체 생성 전에 값을 바꾸는 건 어떻게 이해를 해야 할까요 ?

생성 전에 값을 바꾸면 사실상 객체 생성 이후 캡쳐를 하더라도 바뀐 값으로 캡쳐를 하면 되니 동기화 문제가 전혀 없을 거 같아서요.

캡쳐본 중 위에는 객체 생성(캡쳐) 이후 바꾸면 안되는 예시이고 동기화 등을 고려하였을 때 제가 궁금한 건 캡쳐 전의 값 변경이 왜 캡쳐에 영향을 주느냐는 겁니다. (아래 캡쳐본)

 

public Printer  process(int param){
    int localVar = 1;

    class LocalPrinter implements Printer{
        int value = 0;

        @Override
        public  void print(){
            System.out.println("value  = " + value);
            System.out.println("local value  = " + localVar);
            System.out.println("param = " + param);
            System.out.println("outInstance = " + outInstance);
        }
    }
    LocalPrinter printer = new LocalPrinter();
    localVar = 10;
   // printer.print();
    return printer;
}
public Printer  process(int param){
    int localVar = 1;
    localVar = 10;

    class LocalPrinter implements Printer{
        int value = 0;

        @Override
        public  void print(){
            System.out.println("value  = " + value);
            System.out.println("local value  = " + localVar);
            System.out.println("param = " + param);
            System.out.println("outInstance = " + outInstance);
        }
    }
    LocalPrinter printer = new LocalPrinter();
    //localVar = 10;
   // printer.print();
    return printer;
}

답변 2

0

김영한님의 프로필 이미지
김영한
지식공유자

안녕하세요. 인프린님

다음을 참고해주세요.

https://www.inflearn.com/questions/1233252

감사합니다.

0

안녕하세요, 인프런 AI 인턴입니다.

인프린님의 질문에 답변 드리겠습니다. 자바에서는 메서드 내부에서 정의된 지역 클래스나 익명 클래스가 외부 메서드의 지역 변수를 참조할 때, 해당 변수가 사실상 final인 경우에만 참조가 허용됩니다. ‘사실상 final’이란, 변수에 재할당이 일어나지 않는 경우를 말합니다. 이는 지역 변수가 스택에 저장되며 메서드 실행이 끝나면 사라지는데 반해, 지역 클래스의 객체가 힙 메모리에 저장되어 메서드 실행이 끝난 이후에도 존재할 수 있기 때문입니다. 따라서 안정성을 위해 Java는 값을 변경할 수 없는 (final 또는 사실상 final) 지역 변수만을 캡처할 수 있도록 제한합니다.

첫 번째 예제에서는 localVar의 값을 LocalPrinter 객체 생성 이후에 재할당하려고 시도하였기 때문에 컴파일 에러가 발생합니다. 이 경우, localVar가 사실상 final이 아니게 되어 지역 클래스 내부에서의 사용이 불가능해집니다.

두 번째 예제의 경우, 객체 생성 전에 localVar 값을 변경하는 것은 문제가 없습니다. 이 경우 localVar가 객체 생성 시점에 사실상 final 특성을 유지한다면, 즉 객체 생성 후에는 해당 변수에 대한 재할당이 일어나지 않는다면, 이후 지역 클래스에서 이 값을 안전하게 참조할 수 있습니다.

따라서 객체 생성 전의 값 변경은 객체 생성 시점에 변수가 final이거나 사실상 final 조건을 충족한다면 영향을 주지 않습니다. 핵심은 객체 생성 시점 이후에 해당 변수의 변경 여부이며, 변경이 없다면 동기화 문제나 다른 부작용 없이 값이 캡처되어 사용될 수 있습니다.

인프린님의 프로필 이미지
인프린

작성한 질문수

질문하기