람다란?
자바 8에서 도입된 익명 함수로, 이름 없이 간결하게 함수를 표현한다.
익명 클래스보다 보일러플레이트 코드를 줄여 생산성과 가독성을 높이는 역할을 한다.
-> 익명 클래스를 간소화한 도구지만, 내부적으로 인스턴스가 생성됨
함수형 인터페이스
람다는 추상 메서드가 하나인 함수형 인터페이스에만 할당할 수 있다.
-> 람다도 하나의 함수이다. 람다를 인터페이스에 담으려면 하나의 메서드 선언만 존재해야 한다.
* SAM(Single Abstract Method) : 단일 추상 메서드
* 함수형 인터페이스 : 하나의 추상 메서드를 가진 인터페이스
@FunctionallInterface
public class Car {
public void move() {
System.out.println("차를 이동합니다.");
}
}
public class ElectricCar extends Car {
@Override
public void movee() {
System.out.println("전기차를 빠르게 이동합니다.");
}
}
-> 메서드를 재정의할 때, 부모의 move()를 자식이 movee()라고 잘못 적었다.
-> 이를 컴파일 단계에서 막기 위해 @Override 애노테이션을 사용한다.
이와 비슷하게, 단 하나의 추상 메서드만을 포함한다는 것을 @FunctionallInterface 애노테이션을 사용해 보장한다.
@FunctionalInterface // 애노테이션 추가
public interface SamInterface {
void run();
}
-> 누군가 실수로 추상 메서드를 추가할 경우 컴파일 오류가 발생한다.
람다와 시그니처
람다를 함수형 인터페이스에 할당할 때는 메서드의 형태를 정의하는 요소인 메서드 시그니처가 일치해야 한다.
메서드 시그니처
1) 메서드 이름
2) 매개변수 수와 타입
3) 반환 타입
ex) MyFunction
@FunctionalInterface
public interface MyFunction {
int apply(int a, int b);
}
-> 이름 : apply & 매개변수 : int, int & 반환 타입 : int
MyFunction myFunction = (int a, int b) -> {
return a + b;
};
-> 람다는 익명 함수이므로 시그니처에서 이름을 제외한 매개변수와 반환 타입이 맞아야 함
람다와 생략
1. 매개변수 타입 : 생략 가능하지만 필요시 명시적으로 작성할 수 있다.
2. 반환 타입 : 문법적으로 명시할 수 없고, 식 결과를 보고 컴파일러가 항상 추론한다.
3. 람다는 간략히 사용하는 것을 권장
-> 단일 표현식이면 중괄호, 리턴 생략
-> 타입 추론을 통해 매개변수 타입 생략
// 1. 단일 표현식은 본문과 반환 생략
x -> x + 1
// 2. 타입 추론
// (int x) -> x
(x) -> x
람다의 전달
1. 람다를 변수에 대입하기
MyFunction.java
package lambda;
@FunctionalInterface // 추가
public interface MyFunction {
int apply(int a, int b);
}
LambdaPassMain1.java
package lambda.lambda2;
import lambda.MyFunction;
// 1. 람다를 변수에 대입하기
public class LambdaPassMain1 {
public static void main(String[] args) {
MyFunction add = (a, b) -> a + b;
MyFunction sub = (a, b) -> a - b;
System.out.println("add.apply(1, 2) = " + add.apply(1, 2));
System.out.println("sub.apply(1, 2) = " + sub.apply(1, 2));
// 람다 전달 가능
MyFunction cal = add;
System.out.println("cal(add).apply(1, 2) = " + cal.apply(1, 2));
cal = sub;
System.out.println("cal(sub).apply(1, 2) = " + cal.apply(1, 2));
}
}
-> 람다 인스턴스의 참조값을 함수형 인터페이스로 선언한 변수에 대입
실행 결과

2. 람다를 함수에 전달하기
LambdaPassMain2.java
package lambda.lambda2;
import lambda.MyFunction;
// 2. 람다를 메서드에 전달하기
public class LambdaPassMain2 {
public static void main(String[] args) {
MyFunction add = (a, b) -> a + b;
MyFunction sub = (a, b) -> a - b;
System.out.println("변수를 통해 전달");
calculate(add);
calculate(sub);
}
static void calculate(MyFunction function) {
int a = 1;
int b = 2;
System.out.println("계산 시작");
int result = function.apply(a, b);
System.out.println("계산 결과 : " + result);
}
}
실행 결과

고차 함수
람다는 함수형 인터페이스를 구현한 익명 클래스 인스턴스와 같은 개념으로 이해하면 된다.
즉, 람다를 변수에 대입한다는 것은 람다 인스턴스의 참조값을 대입하는 것이고, 메서드의 매개변수나 반환값으로 넘긴다는 것 역시 람다 인스턴스의 참조값을 전달 / 반환 하는 것
고차 함수(Higher-Order Function)
1. 함수를 인자로 받는 함수
// 함수(람다)를 매개변수로 받음
static void calculate(MyFunction function) {
// ...
}
2. 함수를 반환하는 함수
// 함수(람다)를 반환
static MyFunction getOperation(String operator) {
// ...
return (a, b) -> a + b;
}
-> 보통의 함수는 데이터(값)를 입력으로 받고, 값을 반환한다.
-> "값"을 다루는 것을 넘어 "함수" 개념 자체를 값처럼 다룬다는 점에서 추상화 수준이 한 단계 높아진다고 하여 Higher-Order 함수라고 부른다.
'인프런 > 김영한의 실전 자바 - 고급 3편, 람다, 스트림, 함수형 프로그래밍' 카테고리의 다른 글
| [인프런] 김영한의 실전 자바 - 고급 3편, 람다, 스트림, 함수형 프로그래밍 / 7. 메서드 참조 (0) | 2025.05.28 |
|---|---|
| [인프런] 김영한의 실전 자바 - 고급 3편, 람다, 스트림, 함수형 프로그래밍 / 6. 람다 vs 익명 클래스 (0) | 2025.05.28 |
| [인프런] 김영한의 실전 자바 - 고급 3편, 람다, 스트림, 함수형 프로그래밍 / 5. 람다 활용 (0) | 2025.05.22 |
| [인프런] 김영한의 실전 자바 - 고급 3편, 람다, 스트림, 함수형 프로그래밍 / 4. 함수형 인터페이스 (0) | 2025.05.21 |
| [인프런] 김영한의 실전 자바 - 고급 3편, 람다, 스트림, 함수형 프로그래밍 / 2. 람다가 필요한 이유 (2) | 2025.05.12 |