4. 람다
• 람다 표현식
– 메서드로 전달할 수 있는 익명 함수를 단순화 한 표현식
• 대표적인 특징
– 익명
• 보통의 메서드와 달리 이름이 없으므로 익명이다.
– 함수
• 람다는 메서드처럼 특정 클래스에 종속되지 않으므로 함수이다.
– 전달
• 람다 표현식을 메서드 인수로 전달하거나 변수로 저장할 수 있다.
– 간결성
• 익명 클래스처럼 자질구레한 코드를 구현할 필요가 없다.
5. 주의!
• 람다가 기술적으로 Java8 이전에 할 수 없
었던 일들을 해낸다던가 하는 드라마틱한
기술은 아니다.
– 기존의 익명클래스로 제공되던 파라메터 코드
가 간결해진다는 점
– 좀더 손쉬운 Multi Core 프로그래밍을 제공한
다는 점
8. 람다 기본 문법
// 식을 이용하는 경우 ( = 표현식)
(parameters) -> expression
// 문을 이용하는 경우 ( = 구문)
(parameters) -> {
statements;
}
람다 작성시 “식”과 “문”을 구분해서 생각해야 한다.
“식” 일때는 {}가 생략되지만
“문” 일때는 반드시 {}를 감싸야 한다.
11. 함수형 인터페이스
• 람다 표현식은 함수형 인터페이스라는 문
맥에서만 사용할 수 있다.
• 함수형 인터페이스
– 하나의 추상 메서드만 가지는 인터페이스
12. 함수형 인터페이스
• Java8 이전부터 존재하던 인터
페이스
• 과거부터 존재하던 인터페이스
이지만 Java8 기준으로는 모두
함수형 인터페이스라고 불러도
된다.
13. 함수형 인터페이스
• Java8부터 인터페이스는 디
폴트 메소드를 포함 할 수
있다.
• 다수의 디폴트 메소드를 포
함하고 있더라도 추상 메소
드가 오직 하나라면 함수형
인터페이스이다.
• 인터페이스 내부에 Static
메소드가 정의되어 있더라
도 추상메소드가 오직 하나
라면 함수형 인터페이스이
다.
• @FunctionalInterface 어노
테이션을 제공하고 있으며
추상메소드가 1개 이상이
면 컴파일시 오류가 발생한
다.
14. 함수형 인터페이스
• 람다식을 이용하면 함수형 인터페이스가 가지는 추상메소드에 로직
만을 깔끔하게 인스턴스로 전달할 수 있다.
• 물론 익명클래스도 같은 일이 가능하지만 New 키워드로 객체를 직
접 생성해야 하고 로직을 감싸는 코드들 까지도 모두 구현해야 한다.
15. 함수형 인터페이스
• 람다는 결과적으로 함수형 인터페이스가 가지는 유일한 메소드가 구현되는 것이다.
(이를 바탕으로 타입 추론이 가능해짐)
• 함수형 인터페이스를 인자로 가지는 게스트 코드 입장에서는 코드가 인스턴스화 되
어 인자로 들어오므로 호스트 코드에서 보내는 인스턴스의 정체가 람다인지 익명클
래스인지는 관심이 없다.
• 람다와 익명클래스는 다르다.
– 익명클래스는 컴파일시 서브클래스로 별도의 파일로 컴파일되고 람다는 기존 클
래스에 포함된다.
– 람다는 바이트코드로 변환시 Java7에서 추가된 InvokeDynamic 명령어을 이용하
여 런타임에 코드가 생성된다.
16. Java.util.function 패키지
• 함수형 인터페이스를 인자로 받는 메소드에만 람다식을
사용할 수 있다.
– 새로운 함수형을 추가할 경우 언어가 더 복잡해진다.
– 대부분의 자바 프로그래머가 익명클래스 문법에 익숙하다.
• 위와 같은 제약사항으로 인해 람다식의 타입 추론이 가
능해졌다.
– 함수형 인터페이스가 가지고 있는 추상 메소드가 오직 하나 밖에 없으
므로 이를 이용하여 타입 추론
– 람다식의 Prameter 추론 : 추상 메소드의 파라메터 정보
– 람다식의 Return 타입 추론 : 추상 메소드의 리턴 타입 정보
• Java8에서는 java.util.function 패키지로 다양한 함수형 인터페
이스를 제공한다.
30. 람다 표현식 조합
• Java.util.function 패키지에서 제공하는 함
수형 인터페이스 중 일부는 static 메소드
형태의 유틸리티 메소드를 가지고 있다.
– Predicate
– Function
– Comparator
• 유틸리티 메소드를 조합해서 복잡한 람다
식을 만들수 있다.
31.
32.
33.
34.
35.
36. 기본형 특화 함수형 인터페이스
• Autoboxing
– 박싱(boxing) : 기본형을 참조형으로 변환
– 언박싱(unboxing) : 참조형을 기본형으로 변환
– 오토박싱(autoboxing) : 박싱과 언박싱이 자동으
로 일어나는 것으로 컴파일러가 편의를 위해 제공
한다.
• 오토박싱에 의한 비용을 줄이기 위해서 Java8
에서는 기본형에 특화된 다양한 함수형 인터
페이스를 제공한다.
37.
38. 람다 클로저
• 클로저란 함수의 비지역변수를 자유롭게
참조할 수 있는 함수의 인스턴스를 가르킨
다.
• 람다와 익명클래스 모두 클로저와 비슷하
게 동작한다.
• 자바의 클로저는 비지역변수가 final로 정
의되어야 한다.
– 익명클래스는 final 강제
– 람다는 추론
39. 람다 클로저
Javascript Closure Lambda Closure
다른 함수의 인자로 전달가능 다른 메소드의 인자로 전달가능
클로저 외부에 정의된 변수값에
접근 가능
클로저 외부에 정의된 변수값에
접근 가능 (복사된 레퍼런스)
클로저 외부에 정의된 변수값 변
경 가능
클로저 외부에 정의된 변수값 변
경 불가 (final)
40. 메서드 레퍼런스
• 메서드 레퍼런스를 이용하면 기존의 메서드 정의를 이용
하여 람다처럼 전달할 수 있다.
• 람다식의 내용이 길어지면 가독성이 떨어지기 때문에 메
서드 레퍼런스를 사용하는 것이 바람직하다.
• 메서드 레퍼런스는 특정 메서드만을 호출하는 람다식의
축약형이라고 생각해도 된다.
• 컴파일러 입장에서는 함수형 인터페이스를 보고 추론을
하는 것보다 메서드 레퍼런스를 직접 보고 인스턴스를
만드는 것이 더 효율적이다.
41. 메서드 레퍼런스
• Apple::getWeight
– 연산자 :: 를 이용해서 Apple 클래스의 getWeight 메서드가 메서드 레퍼런스로
동작한다.
– 실제 메서드를 호출하는 것이 아니므로 ()는 생략
– JVM은 런타임에 메서드 레퍼런스의 내용을 인스턴스로 만들어 전달한다.
람다식 메서드 레퍼런스
(Apple a) -> a.getWeight() Apple::getWeight
() -> Thread.currentThead().dumpStack() Thead.currentThread()::dumpStack
(str, i) -> str.substring(i) String::substring
(String s) -> System.out.println(s) System.out::println
42. 생성자 레퍼런스
• 클래스명과 new 연산자를 이용해서 기존
생성자의 레퍼런스를 만들 수 있다.
• 다양한 파라메터를 가지는 생성자가 존재
하더라도 ClassName::new
• 다수의 생성자가 존재할 경우 타입추론에
의해서 생성자를 찾아간다.