[Java] Lambda - Closure
- Java
- 2020. 8. 16.
이번 글에서는 closure에 대해 알아보도록 하겠습니다.
1. Closure
closure란 다른 함수의 scope 변수에 접근할 수 있는 함수를 의미합니다.
1-1) implements interface
예를 들어 다음과 같은 예제가 존재할때
public class Closure {
public static void main(String[] args) {
int a = 10;
int b = 20;
// implements interface
doProcess(a, new Process() {
@Override
public void process(int i) {
System.out.println(i + b);
}
});
}
public static void doProcess(int i, Process p){
p.process(i);
}
}
interface Process {
void process(int i);
}
Process를 구현한 익명 클래스에서 main scope의 변수 b를 사용하고 있는 것을 확인 할 수 있습니다.
이 익명 클래스의 작업은 main method가 아닌 doPrcoess 메서드 내부에서 수행되므로 doProcess scope로 해석할 수 있습니다.
그렇다면, 어떻게.. 다른 scope의 변수값을 사용할 수 있는 것 일까요? 😅
사실, 위와 같이 작성하면 내부적으로.. 컴파일러가 b의 값을 track 하게됩니다.
이후 doProcess 메서드가 실행될때 track 해둔 b의 값을 사용함으로써 에러가 발생하지 않게 되는 것 입니다.
이때의 주의사항으로는 반드시 b의 값은 변경되지 않아야 한다는 것 입니다. 컴파일러는 단순히 declared 된 순간의 변수 값을 track 하는것이므로, changed 된 변수 값은 알 수 가 없습니다.
따라서 이번 예제에서 b의 값을 변경하는 구문을 작성하면 위와 같이 에러가 발생하게 됩니다.
에러의 내용은 "b 변수는 final 혹은 effectively final 이어야 한다" 입니다.
이때 effectively final이란 마치 final 처럼 한번 선언된 변수는 변경되지 말아야 한다로 이해할 수 있습니다.
위와 같이 구문이 작성된 이유는 java7의 경우에는 반드시 해당 변수를 final 선언해줘야 했었는데, java8부터는 final 변수를 선언하지 않더라도.. 변경되지만 않다면 사용할 수 있도록 개선되었기 때문입니다. 😎
1-2) lambda
동일하게 lambda 식으로 변경하면 다음과 같이 작성할 수 있습니다.
public class Closure {
public static void main(String[] args) {
int a = 10;
int b = 20;
// lambda
doProcess(a, i -> System.out.println(i + b));
}
public static void doProcess(int i, Consumer<Integer> p) {
p.accept(i);
}
}
위의 경우에도 closure가 작동해 lambda 식 내부에서 main scope인 b변수를 사용할 수 있습니다.
추천서적
파트너스 활동을 통해 일정액의 수수료를 제공받을 수 있음
'Java' 카테고리의 다른 글
[Java] Lambda - Method Reference (0) | 2020.08.16 |
---|---|
[Java] Lambda - This Reference (0) | 2020.08.16 |
[Java] Lambda - Exception Handling (0) | 2020.08.16 |
[Java] Lambda - Functional Interface (0) | 2020.08.16 |
[Java] Lambda - Using Lambda (0) | 2020.08.16 |