자바스크립트를 사용하다보면 종종 클로저를 사용할 때가 있습니다. 아래와 같이 말이죠.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function Vo() {
    var data;
    
    return {
        getData : function() {
            return data;
        },
 
        setData : function(value) {
            data = value;
        }
    }
}
 
var closure = Vo();
closure.setData('Hello world');
console.log(closure.getData()); // Hello world
cs


클로저의 구조를 보게되면 함수 안에 내부함수가 존재하며, 이 내부함수는 인스턴스같이 외부로 넘겨지기도 하고 비지역변수를 자유롭게 변경이 가능합니다. 


람다나 익명클래스 역시도 저 동작과 비슷한 작업을 수행할 수 있습니다. 

함수를 인수로 넘기는 것이 가능하며, 메소드 내부에 함수를 선언할 수 있습니다. 

(아래 예제는 메소드 내부에 람다를 표현했고, 외부변수 x를 변경하였습니다.)


1
2
3
4
5
6
7
8
9
private int x = 0;
    
public void func(){
    int data = 0;
        
    IntConsumer setData = (int a) -> x = a;
    setData.accept(5);
}
 
cs


"JAVA 8 IN ACTION" 에서는 이러한 점 때문에 람다가 클로저의 정의에 부합하는가에 대해서 다루고 있습니다. 


결론부터 말하면, 서로 비슷한 일을 하고는 있지만 람다의 경우 선언된 지역변수의 데이터를 변경할 수 없습니다. 

지역변수가 람다 내부에서 사용되려면 final 한 상태이어야 합니다. 혹은 final과 같은 동작을 하거나 말이죠 ㅡㅡ^

(아래 예제는 람다 표현식에서 지역변수 data를 변경하려 하지만, 이 것은 문법 오류라고 체크하게 됩니다.)


1
2
3
4
5
6
7
public void func(){
    int data = 0;
         // 문법 오류
    IntConsumer setData = (int a) -> data = a;
    setData.accept(5);
}
 
cs


위와 같은 이유는 지역 변수 값의 경우 스택에 존재하며, 해당 메소드의 스레드 생명주기와 동일하게 종료되어야 합니다. 

이것이 보장되지 않는다면 람다 내부 블럭이 실행 시, 안전하지 않은 동작이 수행되겠죠.

(멤버 변수의 경우 힙에 있으므로, 람다에 대해 특별한 제약이 없습니다.) 



자바 8 인 액션
국내도서
저자 : 라울-게이브리얼 우르마(RAOUL-GABRIEL URMA),마리오 푸스코(MARIO FUSCO),앨런 마이크로프트(ALAN MYCROFT) / 우정은역
출판 : 한빛미디어 2015.04.01
상세보기


반응형
Posted by N'