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

콩이하마님의 프로필 이미지
콩이하마

작성한 질문수

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

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

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

작성

·

183

0

안녕하십니까 깊은 내용 쉽게 가르쳐 주셔서 정말 감사합니다.

질문이 있습니다.

public static void main(String[] args) {
    OuterClassV2 outerClassV2 = new OuterClassV2();
    Printer innerPrinter = outerClassV2.process(1);

    innerPrinter.print();
    Field[] fields = innerPrinter.getClass().getDeclaredFields();

    System.out.println(fields.length);
    for (Field field:
         fields) {
        System.out.println(field.getName());

    }
}

위 메서드 실행시에

public Printer process(final int paramVal) {
    int localVal = 2; // 여기
    
    class InnerPrinter implements Printer{
        private final int val = 3;

        @Override
        public void print() {
            System.out.println("val = " + val);
            System.out.println("localVal = " + localVal);
            System.out.println("paramVal = " + paramVal);
            System.out.println("outerClassVal = " + outerClassVal);
        }
    }

    return new InnerPrinter();
}

위와 같이 int localVal = 2 처럼 암묵적 final을 이용하면
지역 클래스에 캡쳐되는게 확인 됩니다 하지만

final int localVal = 2 처럼 명시적으로 하면 지역클래스가 캡쳐되지 못하는데 이유가 무엇일까요?

크게 중요한 문제는 아니지만 궁금하였습니다.

감사합니다.

답변 2

0

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

안녕하세요. 콩이하마님

이 부분은 자바 컴파일러 최적화와 관련이 있는데요.

localVar를 final로 명시적으로 선언하면, 컴파일러는 이 변수가 절대 변경되지 않음을 확신합니다.

이 경우, 컴파일러는 최적화를 수행하여 LocalPrinter 클래스 내에 별도의 필드(val$localVar)를 생성하지 않고, 직접 값을 인라인으로 삽입할 수 있습니다.

감사합니다.

0

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

콩이하마님의 질문에 대해 답변 드립니다.

자바에서 지역 클래스 또는 익명 클래스 내부에서는 외부 메서드의 지역 변수를 직접 접근할 수 있습니다. 이때, Java 8 이전에는 지역 변수가 final로 선언되어 있어야만 접근이 가능했습니다. Java 8부터는 final이 아닌 변수에 대해서도 접근할 수 있게 되었는데, 이 경우 변수는 사실상 final(Effectively Final)이어야 합니다. 이는 변수에 대한 후속 변경이 없을 때를 의미합니다.

질문하신 코드의 경우, final int localVal = 2;처럼 명시적으로 final을 사용했을 때와 int localVal = 2;처럼 사용했을 때 모두 localVal은 실질적으로 변경되지 않아 Effectively Final의 조건을 만족합니다. 따라서 둘 다 지역 클래스에 의해 캡쳐될 수 있습니다.

만약 지역 클래스가 캡쳐되지 못한다고 느껴진다면, 그것은 다른 이유일 수 있습니다. 예를 들어, 캡쳐되는 지역 변수가 실제로 클래스의 필드로 복사되는지를 확인하는 방법 등에서 오해가 있을 수 있습니다. 실제로 지역 클래스 또는 익명 클래스가 외부 지역 변수를 사용할 경우, 해당 값은 클래스 내부에 복사되어 사용됩니다. 즉, final 또는 Effectively Final 조건을 만족하는 지역 변수는 모두 정상적으로 캡쳐될 수 있습니다.

정리해서, 명시적으로 final을 선언하든 안 하든, 변수가 변경되지 않아 Effectively Final의 조건을 만족한다면 지역 클래스에 의해 캡쳐될 수 있습니다. 오류나 예상과 다른 동작이 발생한다면, 캡쳐 과정이나 변수 접근에 대한 코드의 다른 부분을 확인해보아야 할 것입니다.

질문에 직접적으로 관련된 공식 문서나 모범 사례에 대한 참고자료는 제공된 정보 내에 없습니다. 따라서 Java의 기본 원칙과 규칙에 대한 설명으로 대체하여 답변 드렸습니다. 추가적인 공부가 필요하시다면 Java의 지역 클래스, 익명 클래스, 그리고 클로저(closure)에 대해 다루는 자료를 참고하시는 것이 좋을 것 같습니다.

콩이하마님의 프로필 이미지
콩이하마

작성한 질문수

질문하기