Java에서 함수형 프로그래밍은 람다 표현식과 함수형 인터페이스가 도입되면서 발전하였습니다 (Java 8부터).
문제의 역사
Java 8 이전에는 모든 인터페이스가 추상 메소드의 집합으로 구성되어 있었으며, 패러다임은 OOP에 초점을 맞추고 있었습니다. 함수형 인터페이스와 람다 표현식의 도입으로 더 간결한 코드를 작성하고 FP의 원칙을 따를 수 있게 되어 코드의 가독성과 표현력이 향상되었습니다.
문제
이벤트 처리, 컬렉션 또는 비동기 로직과 관련된 코드는 과도해졌습니다: 별도의 클래스나 익명 내부 클래스를 생성해야 했습니다. 이는 코드의 유지보수와 확장을 어렵게 만들었습니다.
해결책
함수형 인터페이스는 정확히 하나의 추상 메소드를 가진 인터페이스입니다. 이를 람다 표현식의 목적지로 사용할 수 있습니다. 표준 라이브러리에는 Function<T, R>, Predicate<T>, Supplier<T>, Consumer<T>와 같은 일반적인 함수형 인터페이스들이 제공되며, 자신만의 인터페이스를 만들 수도 있습니다.
코드 예시:
import java.util.function.Function; public class FunctionalExample { public static void main(String[] args) { // 표준 함수형 인터페이스 Function Function<String, Integer> stringLength = s -> s.length(); System.out.println(stringLength.apply("Java")); // 4를 출력합니다. } }
주요 특징:
여러 개의 추상 메소드를 가진 함수형 인터페이스를 기본 메소드나 정적 메소드를 포함하여 선언할 수 있나요?
아니요, 함수형 인터페이스는 오직 하나의 추상 메소드만 포함할 수 있습니다. 기본 메소드(default)나 정적 메소드는 가질 수 있습니다.
여러 개의 추상 메소드를 가진 다른 인터페이스로부터 함수형 인터페이스를 상속할 수 있나요?
아니요, 최종 인터페이스가 하나 이상의 추상 메소드를 가지게 되면 더 이상 함수형이 아니므로 람다 표현식으로 대체할 수 없습니다.
Java의 함수형 인터페이스와 C#의 SAM 인터페이스는 어떻게 다르나요?
Java에서는 @FunctionalInterface 애노테이션이 도입되기 전까지 SAM 인터페이스를 선언하는 전용 키워드가 없었습니다. C#에서 delegate는 명확하게 시그니처를 정의하는 것과 달리, Java에서는 하나의 추상 메소드와 선택적인 애노테이션으로 컴파일러가 처리합니다.
@FunctionalInterface 애노테이션을 잊어버리는 것 — 인터페이스가 함수형이 아닐 경우 컴파일러가 즉시 오류를 발생시키지 않습니다.대규모 프로젝트에서 모든 곳에서 람다를 사용하는 것을 결정하였고, 데이터 표현의 엔티티에 비즈니스 로직과 직접적으로 관련 없었던 곳에서도 사용하였습니다. 그 결과 복잡한 로직을 추적하기 어려워졌고, 람다가 코드의 의도를 가리게 되어 디버깅이 힘들어졌습니다.
장점:
단점:
다른 프로젝트에서는 어떤 인터페이스가 FP에 적합한지 철저하게 분석하였습니다. 컬렉션 및 이벤트 처리를 위해 Predicate, Function 및 자작 인터페이스를 사용했습니다. 데이터와 엔티티 저장을 위해 FP는 적용하지 않았습니다.
장점:
단점: