기록/JAVA
[JAVA8] 람다 표현식
jeongdalma
2021. 1. 10. 00:44
람다
- (인자 리스트) -> {바디}
BinaryOperator <Integer> test = (a , b) -> a + b;
인자 리스트
- 인자가 없을 때 : ()
- 인자가 한 개 일 때 : (one) 또는 one
- 인자가 여러 개 일 때 : (one , two)
- 인자의 타입은 생략 가능 , 컴파일러가 추론 (infer) 하지만 명시할 수도 있다. (Integer one , Integer two)
바디
- 화살표 오른쪽에 함수 본문을 정의한다.
- 여러 줄인 경우에 {}를 사용해서 묶는다.
- 한 줄인 경우에 생략 가능 , return도 생략 가능
변수 캡처 (Variable Capture)
- 로컬 변수 캡처
- final 이거나 effective final 인 경우에만 참조할 수 있다.
- 그렇지 않을 경우 concurrency(동시성) 문제가 생길 수 있어서 컴파일러가 방지한다.
- effective final
- 이것도 역시 자바 8 부터 지원하는 기능으로 "사실상" final인 변수이다.
- final 키워드를 사용하지 않은 변수를 익명 클래스 구현체 또는 람다에서 참조할 수 있다.
- 람다 표현식은 익명 클래스 구현체와 달리 "쉐도윙" 하지 않는다.
- 익명 클래스는 새로 scope(범위)를 만들지만 , 람다는 람다를 감싸고 있는 scope(범위)와 같다.
private void run(){
// final 없어도 참조가 가능하다.
// final 없지만 어디에서도 이 변수를 수정하지 않는 것 (사실상 final - effective final)
int baseNumber = 10;
// 쉐도윙
// Foo class -> run method -> 람다 , 익명 클래스 , 내부 클래스
// 내부 클래스 , 익명 클래스 - 쉐도윙이 일어난다.
// 람다 - 쉐도윙이 일어나지 않는다.
// 람다 표현식 지역 변수 참조
IntConsumer printInt = (i) -> {
int baseNumber = 11;
System.out.println(i + baseNumber);
};
printInt.accept(10);
// 익명 클래스에서 지역 변수 참조
Consumer<Integer> test2 = new Consumer<Integer>() {
@Override
public void accept(Integer integer) {
int baseNumber = 12;
System.out.println(baseNumber);
}
};
// 내부(로컬) 클래스에서 지역 변수 참조
class LocalClass{
void printBaseNumber(){
int baseNumber = 13;
System.out.println(baseNumber);
}
}
}
- 람다 scope 안의 int baseNumber = 11;은 컴파일 에러가 난다. (쉐도윙이 일어나지 않는다.)
- 람다 표현식의 scope(범위)와 메소드의 scope가 동일하다.
- scope가 동일하기 때문에 baseNumber가 변경된다면 컴파일 에러가 발생한다.
- 하지만 익명 클래스와 내부 클래스는 쉐도윙이 일어난다.
- 익명 클래스와 내부 클래스에서 선언된 baseNumber가 run 메소드의 baseNumber를 덮어 버린다.
더 자바, Java 8 - 인프런
자바 8에 추가된 기능들은 자바가 제공하는 API는 물론이고 스프링 같은 제 3의 라이브러리 및 프레임워크에서도 널리 사용되고 있습니다. 이 시대의 자바 개발자라면 반드시 알아야 합니다. 이
www.inflearn.com