반응형
람다
- 익명 함수의 구현 중 하나
- 클래스, 메소드에 종속되지 않고 이름이 따로 필요하지 않다.
- 파라미터를 입력해 반환값을 설정하는 로직을 간단하게 넣을 수 있다.
- 순수한 람다는 외부의 상태값을 사용하지 않고 파라미터와 람다 내부의 로직을 통해서만 리턴값을 생성한다.
- 예시)
private Function<Integer, Integer> square = x -> x * x;
@Test
public void lambdaTest() {
System.out.println(square.apply(3));
}
클로저
- 클래스나 메소드에서 정의한 변수를 람다 내부에서 사용할 수 있는 것을 의미한다.
- 람다에서 정의하지 않고 외부에서 정의한 변수를 자유 변수(free variable)이라고 한다.
- 람다 내부에서 사용되는 자유 변수는 인스턴스 변수와 지역 변수를 사용할 수 있다.
- 예시로 문장을 단어 리스트로 분석하는 클래스와 메소드를 만들어보았다.
public class Analyzer {
private List<String> stopwords = List.of("is", "a", "test", "spam");
public List<String> analyze(String sentence) {
String queryStr = "";
Function<String, List<String>> tokenize = x -> {
queryStr = x; //컴파일 에러!
stopwords = new ArrayList<>(); // 가능
return Arrays.stream(x.split(" "))
.collect(Collectors.toList());
};
Function<List<String>, List<String>> filtering = x -> x.stream()
.filter(word -> !stopwords.contains(word)).collect(Collectors.toList());
return tokenize.andThen(filtering).apply(sentence);
}
}
- 람다에서 인스턴스 변수와 지역 변수의 차이점은 변수의 재할당이 가능한지 가능하지 않은지의 차이가 있다.
- 위의 지역 변수 queryStr를 람다 내부에서 할당하려고 하면 IDE에서 컴파일 에러 문구를 표시한다.
- 변수는 람다 표현식 내에서 final로 선언돼있거나 final처럼 작동해야 한다고 한다.
- Variable used in lambda expression should be final or effectively final
- 변수는 람다 표현식 내에서 final로 선언돼있거나 final처럼 작동해야 한다고 한다.
- analyzer 클래스 인스턴스 변수인 stopwords는 람다 내부에서 새로 할당하더라도 문제가 없다.
그렇다면 왜 인스턴스 변수는 재할당이 가능하고 지역 변수는 불가능할까?
- 인스턴스 변수는 힙 메모리에 올라가 서로 다른 스레드에서 접근이 가능하므로 재할당 하더라도 문제가 없다.
- 지역 변수의 경우에는 각 스레드의 영역인 스택에 저장이 되기 때문에 람다 내부에 외부의 지역 변수를 사용하게 되면 람다를 실행하는 스레드가 변경된다면 원래대로라면 해당 지역 변수는 소멸되어 사용할 수가 없다.
- 하지만 자바에서는 편의성을 위해 외부 지역 변수를 람다 내부에서 사용하게 되면 지역 변수가 복사되어 람다 인스턴스에 담겨 외부 지역변수가 없어지더라도 사용할 수 있어서 마치 람다 내부에서 선언한 지역변수처럼 된다.
이를 람다 캡처링이라고 한다. - 지역 변수의 재할당이 불가능한 이유는 A 스레드에서 생성한 지역 변수가 복사되어 람다에 담기고, 람다의 실행이 B 스레드에서 이뤄질때 A 스레드에서 해당 지역 변수가 변경이 가능하다면 B 스레드의 해당 변수 사용 시점에 그 변수가 어떤 값을 가질지 예측할 수가 없게 된다.
- 그렇기 때문에 람다에서 사용하는 외부 지역 변수는 변경이 불가능해야 한다.
- 실제 개발에 활용을 한다면 인스턴스 변수도 final이거나 재할당해서 사용하지 않는 것이 좋은데,
지역 변수와 같은 이유로 side effect가 생길 수 있기 때문이다.
반응형
'개발 > java' 카테고리의 다른 글
[java] junit5 (0) | 2024.06.16 |
---|---|
[java] IntelliJ 자바 개발시 애플리케이션 성능 높이는 방법 (0) | 2024.01.26 |