본문 바로가기

Development/Java

람다 표현식에서 참조하는 지역 변수가 꼭 final이어야 하는 이유

람다 캡처링(Capturing lambda)



람다 표현식에서는 익명 함수에서와 마찬가지로, 외부에서 정의된 변수(* 책에서는 자유변수free variable 라고 소개됨)를 활용할 수 있다.

(이와 같은 액션을 람다 캡처링(capturing lambda)라고 소개되어 있다)


즉, 람다 표현식에서는 인스턴스 변수, 정적 변수등을 자유롭게 body에서 참조하여 사용할 수 있다.

하지만 지역 변수를 사용하기 위해서는 지역 변수가 반드시 final 로 선언되어 있어야 한다는 제약 조건이 있다.


1
2
3
4
5
6
7
8
9
10
11
// In Any Method...
{
 
...
 
String name = "Variable";
Runnable r = () -> System.out.println(name);
 
...
 
}
cs


-- Compile Error !


왜 final 제약 조건을 걸어 두었을까?



인스턴스 변수는 heap영역에 저장이 되고, 지역 변수는 stack영역에 위치한다.


이런 상황에서 람다가 스레드에서 실행된 후, 변수를 할당한 스레드가 사라져 stack 메모리에서 해제되었으나, 람다를 실행하는 스레드는 살아 있어 해당 변수에 접근을 요청할 케이스가 생긴다.


이와 같은 이유로 ,

실제 변수에 접근을 허용하는 것이 아닌 해당 변수의 복사본을 만들어 그 곳에 접근을 허용하는데

당연히 처음에 복사한 값과 원본의 값이 달라지면 안되기 때문에, 람다에서 접근하는 지역 변수는 final로 선언되어야 한다.



참고 : Java 8 In Action