본문 바로가기
Programming Language/Java

람다 표현식에서 상수를 사용하는 이유

by 델버 2023. 10. 29.
  • 모던 자바 인 액션을 읽다가, 람다 표현식에서 지역 변수를 사용하는 경우 지역 변수는 final로 선언되거나 final로 취급되어야 한다고 읽었다. 결국 람다 표현식에서 사용하는 지역변수는 재할당할 수 없다는 것이다. 근데 람다에서는 final을 사용하는지 궁금해서 GodPT에게 아뢰었다.
  • 나중에 생각날까봐 남겨둔다.

delvering 

람다가 스레드에서 실행되면 변수를 할당한 스레드가 사라져서 변수 할당이 해제되었는데 람다를 실행하는 스레드에서 해당 변수에 접근하려 할 수도 있다. 라는 문장을 읽었는데 int portNumber = 1333; Runnable r = () -> System.out.println("portNumber = " + portNumber); 여기서 portNumber = 8080;을 하게되면 람다 표현식에서 컴파일에러가 나는 이유를 설명하는 문장이야 근데 이해가 안됨 더 쉽게 설명 좀해줘 다른 예시도 들면서 말야

GodPT

이 문제는 자바의 람다 표현식과 변수 범위에 관련된 것입니다. 자바의 람다 표현식은 자신을 포함하는 범위의 변수를 캡처할 수 있습니다. 그러나 이때, 캡처된 변수는 최종적으로 할당된 값에 대한 복사본을 갖고 있습니다.

예를 들어, 당신이 제시한 코드에서 **portNumber**는 람다 표현식에서 사용되는 변수입니다. 그러나 람다가 실행될 때, 람다 표현식은 **portNumber**의 값을 복사합니다. 이 경우, 람다가 실행될 때 이미 **portNumber**의 값은 1333입니다. 그래서 람다는 이 값을 사용합니다.

만약 당신이 **portNumber**에 새로운 값을 할당한다면, 이는 람다가 사용하는 복사본과는 관련이 없습니다. 람다가 이미 1333을 캡처했으므로, 이후의 변경 사항은 람다에 영향을 주지 않습니다. 그래서 컴파일러는 람다 내부에서 **portNumber**의 값이 1333이라고 가정하고, 이후에 **portNumber**에 대한 변경은 반영되지 않습니다. 그래서 당신이 8080을 할당하려고 하면 컴파일러는 이를 알 수 없기 때문에 에러를 발생시킵니다.

더 구체적인 예를 들어볼까요? 예를 들어보면,

public class LambdaExample {
    public static void main(String[] args) {
        int portNumber = 1333;
        Runnable r = () -> System.out.println("portNumber = " + portNumber);
        r.run(); // 이 부분에서 "portNumber = 1333"이 출력됩니다.

        // portNumber = 8080; // 여기서 컴파일 에러가 발생합니다.
    }
}

 

  • 하지만 왜 컴파일러는 8080을 할당하는데 알 수 없는지 궁금했다.

delvering

컴파일러의 관점으로 다시 설명좀

GodPT

물론입니다. 자바의 람다 표현식은 변수를 캡처할 수 있지만, 이때 캡처된 변수는 사실상 final 또는 effectively final이어야 합니다. 이는 람다 표현식이 변수를 변경하지 않도록 보장하는 것입니다.

따라서 여기서 **portNumber**를 1333으로 초기화한 후 람다 표현식에서 사용하면, 컴파일러는 **portNumber**를 람다 표현식 내부에서 사용할 수 있습니다. 그러나 이후에 **portNumber**에 다른 값을 할당하면, 람다 표현식이 캡처한 값을 변경할 수 없습니다. 그래서 컴파일러는 이를 에러로 처리합니다.

이를 더 명확히 설명하면, **portNumber**를 람다 표현식에서 사용할 때, 실제로는 **final int**로 처리됩니다. 만약 당신이 **portNumber**에 다른 값을 할당하면, 이는 final 변수의 특성에 어긋나기 때문에 컴파일러는 이를 에러로 간주합니다.

즉, 컴파일러의 관점에서는 람다 표현식이 포착한 변수를 변경할 수 없도록 보장하여 안정성을 유지하고, 이러한 원칙을 위반하면 컴파일 오류를 발생시킵니다.

 

  • 결국엔 컴파일러 관점에서는 람다 표현식이 사용하는 변수의 안정성을 위해 final로 처리한다는 것이다.

댓글