[Reactive Programming] 4. 람다, 메서드 레퍼런스, 함수 디스크립터

y001·2025년 4월 19일

Reactive Programming

목록 보기
4/30
post-thumbnail

함수형 인터페이스 (Functional Interface)

함수형 인터페이스는 오직 하나의 메서드만 가지는 인터페이스이다. 자바에서는 이 인터페이스를 통해 함수를 값처럼 전달할 수 있으며, 람다 표현식의 대상이 되는 타입이기도 하다. 자바 8 이전에는 익명 클래스를 사용해야 해서 코드가 복잡하고 길어졌다. 예를 들어 두 수를 더하는 연산을 표현할 때, 람다를 사용하지 않으면 다음과 같이 작성해야 한다.

BinaryOperator<Integer> add = new BinaryOperator<Integer>() {
    @Override
    public Integer apply(Integer x, Integer y) {
        return x + y;
    }
};

람다 표현식 (Lambda Expression)

람다 표현식은 이름 없이 기능만 정의하는 익명 함수를 간단하게 표현하는 문법이다. 자바는 함수 자체를 값처럼 쓸 수 없기 때문에, 함수형 인터페이스를 이용해 함수를 대신 전달하고, 이때 람다 표현식을 구현체처럼 사용할 수 있다. 예를 들어, 자바 8부터는 람다 표현식을 사용해 익명함수를 간결하게 작성할 수 있다.

BinaryOperator<Integer> add = (x, y) -> x + y;

메서드 레퍼런스 (Method Reference)

람다 표현식에서 메서드 한 개만 호출하는 경우, 메서드 레퍼런스를 사용하면 코드를 더 짧고 보기 쉽게 만들 수 있다. 이때 :: 기호로 메서드를 직접 참조한다.

유형표현설명
정적 메서드 참조ClassName::staticMethod정적 메서드 호출
타입의 인스턴스 메서드 참조ClassName::instanceMethod람다 매개변수를 수신자로 사용
객체의 인스턴스 메서드 참조object::instanceMethod특정 객체의 메서드 참조
생성자 참조ClassName::new생성자 호출

정적 메서드 참조 — ClassName::staticMethod

정적 메서드를 참조하는 형태로, 다음과 같이 사용한다.

list.stream()
    .map(StringUtils::capitalize);

특정 타입의 인스턴스 메서드 참조 — ClassName::instanceMethod

해당 타입의 객체가 주어졌을 때 호출 가능한 인스턴스 메서드를 참조한다.

list.stream()
    .map(String::toUpperCase);

이는 s -> s.toUpperCase()와 동일한 표현이다. 스트림의 요소가 String 타입인 경우 유용하게 사용된다.

특정 객체의 인스턴스 메서드 참조 — object::instanceMethod

이미 생성된 객체의 메서드를 참조하는 방식이다.

MyFormatter formatter = new MyFormatter();

list.stream()
    .map(formatter::format);

객체를 기반으로 한 고정된 메서드를 사용할 경우 적합하다.

생성자 참조 — ClassName::new

객체를 생성하는 생성자를 참조할 수 있다. 주로 스트림에서 변환 작업 시 사용된다.

list.stream()
    .map(User::new);

이 경우 User(String name) 생성자가 존재해야 하며, s -> new User(s)를 간결하게 표현한 형태이다.

함수 디스크립터 (Function Descriptor)

함수 디스크립터는 함수형 인터페이스가 어떤 입력값을 받고 어떤 값을 반환하는지를 간단하게 표현한 것이다. 람다 표현식은 이 형태(입력 → 출력)가 일치하는 인터페이스에 자동으로 연결된다.

인터페이스디스크립터설명
Predicate<T>(T) -> boolean입력값을 평가하여 true/false 반환
Consumer<T>(T) -> void입력값을 소비하고 반환하지 않음
Function<T, R>(T) -> R입력값을 변환하여 결과 반환
Supplier<T>() -> T입력 없이 값 생성
BiPredicate<T, U>(T, U) -> boolean두 입력값을 평가하여 boolean 반환
BiConsumer<T, U>(T, U) -> void두 입력값을 받아 처리
BiFunction<T, U, R>(T, U) -> R두 입력값을 받아 결과 반환

0개의 댓글