람다 표현식의 등장과 개념
(Java 8 이후부터)람다(Lambda) 표현식은 함수형 프로그래밍 스타일을 자바에 적용하기 위한 핵심 요소로, 람다 대수(Lambda Calculus)에서 유래했다.
-
배경: 람다와 스트림의 등장은 함수형 패러다임의 등장에 따른 것으로, 기존 클래식 자바 방식의 장황한 컬렉션 처리 방식을 개선하기 위함이다.
-
구조: 람다는
(매개변수 리스트) -> {몸통}구조를 가지며, 메소드를 하나의 식으로 표현한다. -
특징: 메소드의 매개 변수로 전달할 수 있고, 메소드의 결과로 반환이 가능하다. 이는 자바에서 함수를 일급 객체(First-Class Citizen)로 사용할 수 없는 단점을 보완한다.
함수형 인터페이스
람다 표현식은 함수형 인터페이스(Functional Interface)를 통해서만 사용될 수 있다. 람다는 이 인터페이스의 유일한 추상 메소드를 구현하는 역할을 한다.
-
정의: 인터페이스 내에 단 한 개의 추상 메소드만 정의된 인터페이스이다.
-
용도: 외부에서 메소드를 호출 시 람다식이나 메소드 참조(::)가 가능하다.
-
표시: 함수형 인터페이스임을 명확히 하기 위해
@FunctionalInterface어노테이션을 사용한다.
람다의 장점 및 단점
람다의 장점과 단점을 정리한 표는 다음과 같다.
| 구분 | 장점 | 단점 |
|---|---|---|
| 코드 스타일 | 기존에 익명 클래스로 작성하던 코드를 줄여 간단하게 작성 가능하다. | 남용하면 코드를 이해하는 데 어려움을 줄 수 있다. |
| 가독성 | 가독성이 증가한다. | 까다로운 재귀 활용 및 디버깅이 익명 클래스 방식보다 복잡할 수 있다. |
| 병렬 처리 | 병렬 프로그래밍에 용이하다. | - |
컴파일러가 람다를 처리하는 방법
람다 표현식은 익명 함수(익명 클래스)와는 다르게 컴파일된다.
| 구분 | 차이점 |
|---|---|
| 익명 클래스 | 별도 클래스의 인스턴스를 생성하며, 별도의 클래스 파일이 생성된다. 바이트 코드에서 new 연산을 이용해 인스턴스를 생성하는 코드가 보인다. |
| 람다 표현식 | 별도의 클래스 파일이 생성되지 않는다. |
-
invokedynamic이용 런타임 처리: 람다 표현식은invokedynamic바이트 코드 명령어를 사용하여, 람다 표현식 구현을 위한 코드 생성을 런타임 시까지 연기한다.- 최적화: 런타임 시에 어떤 방법으로 객체를 생성할지 결정하며, 성능 향상을 위한 최적화된 방법을 동적으로 사용한다.
-
결론: 람다 표현식은 익명 클래스의 편의 문법이 아니며,
invokedynamic명령으로 람다 변환 전략을 전타임으로 미루고, 런타임은 람다 표현식을 평가할 때 적절한 전략을 동적으로 선택함으로써 높은 효율성을 보장한다.