들어가며
자바 8에서 도입된 함수형 인터페이스(Functional Interface)는 현대 자바 프로그래밍의 핵심 개념 중 하나입니다. 람다식과 스트림 API의 기반이 되는 함수형 인터페이스에 대해 알아보겠습니다.
함수형 인터페이스란?
함수형 인터페이스는 단 하나의 추상 메서드만을 가지는 인터페이스를 의미합니다. Java 8부터 도입되었으며, @FunctionalInterface
어노테이션을 통해 함수형 인터페이스임을 명시적으로 선언할 수 있습니다.
예시:
@FunctionalInterface
public interface SimpleFunction {
void doSomething();
}
주요 함수형 인터페이스
1. Function<T,R>
- 입력값 하나와 리턴값이 있는 가장 기본적인 함수형 인터페이스
R apply(T t)
메서드를 가짐
Function<T, R>
R apply(T t)
예시
Function<String, Integer> strLength = str -> str.length();
System.out.println(strLength.apply("Hello")); // 출력: 5
2. Predicate
- 조건식을 표현하는데 사용(매개변수 하나)
- boolean 값을 리턴하는
test(T t)
메서드를 가짐
Predicate<T>
boolean test(T t)
예시
Predicate isEmpty = str -> str.isEmpty();
System.out.println(isEmpty.test("")); // 출력: true
3. Consumer
- 입력값만 있고 리턴값이 없는 인터페이스
void accept(T t)
메서드를 가짐
Consumer<T>
void accept(T t)
예시
Consumer printer = str -> System.out.println(str);
printer.accept("Hello World"); // 출력: Hello World
4. Supplier
- 입력값 없이 리턴값만 있는 인터페이스
T get()
메서드를 가짐
Supplies<T>
T get()
Supplier random = () -> Math.random();
System.out.println(random.get()); // 랜덤값 출력
함수형 인터페이스의 장점
- 간결한 코드
- 람다식을 통해 익명 클래스를 더 간단하게 표현할 수 있습니다.
- 재사용성
- 공통적인 함수형 인터페이스를 여러 곳에서 재사용할 수 있습니다.
- 유연성
- 다양한 동작을 하나의 메서드로 처리할 수 있습니다.
커스텀 함수형 인터페이스 생성
@FunctionalInterface
interface MathOperation {
int operate(int a, int b);
}
public class Calculator {
public static void main(String\[\] args) {
MathOperation addition = (a, b) -> a + b;
MathOperation multiplication = (a, b) -> a \* b;
System.out.println(addition.operate(5, 3)); // 출력: 8
System.out.println(multiplication.operate(5, 3)); // 출력: 15
}
}
주의사항
- 단일 추상 메서드
- 함수형 인터페이스는 반드시 하나의 추상 메서드만 가져야 합니다.
- default 메서드나 static 메서드는 여러 개 가질 수 있습니다.
- @FunctionalInterface 어노테이션
- 선택사항이지만, 컴파일 타임에 검증을 위해 사용을 권장합니다.
람다 표현식이란?
람다 표현식은 간단히 말해서 "메서드를 하나의 식으로 표현한 것"입니다. 익명 함수(Anonymous Function)를 생성하기 위한 식으로, Java 8부터 도입되었습니다.
(매개변수) -> { 실행문 }
람다 표현식의 다양한 형태
1. 가장기본적인 형태
// 기존 방식
Runnable runnable = new Runnable() {
@Override
public void run() {
System.out.println("Hello");
}
};
// 람다 표현식
Runnable runnable = () -> System.out.println("Hello");
2. 매개변수가 있는 경우
// 매개변수 한 개
Consumer<String> consumer = (String str) -> System.out.println(str);
// 매개변수 타입 생략 가능
Consumer<String> consumer = str -> System.out.println(str);
// 매개변수 여러 개
BiFunction<Integer, Integer, Integer> add = (x, y) -> x + y;
3. 본문이 여러줄인 경우
BiFunction<Integer, Integer, Integer> calculate = (x, y) -> {
int result = x + y;
System.out.println("결과: " + result);
return result;
};
실제 활용 예시
1. 컬렉션 처리
BiFunction<Integer, Integer, Integer> calculate = (x, y) -> {
int result = x + y;
System.out.println("결과: " + result);
return result;
};
2. 스트림 API와 함께 사용
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
// 필터링, 매핑, 집계 연산
int sum = numbers.stream()
.filter(n -> n % 2 == 0) // 짝수 필터링
.map(n -> n * 2) // 2배로 변환
.reduce(0, (a, b) -> a + b); // 합계 계산
3. 이벤트 처리
button.addActionListener(e -> System.out.println("버튼 클릭됨"));
람다 표현식의 장점:
- 코드의 간결성: 불필요한 코드를 줄여줍니다
- 가독성 향상: 의도를 더 명확하게 표현할 수 있습니다
- 함수형 프로그래밍 지원: 함수를 일급 객체처럼 다룰 수 있습니다
- 병렬 처리 용이: 컬렉션의 병렬 처리를 더 쉽게 구현할 수 있습니다
주의사항:
- 람다 표현식 내에서 사용되는 지역변수는 final이거나 effectively final이어야 합니다
- 람다 표현식에서 this는 람다를 감싸는 클래스를 가리킵니다
- 너무 복잡한 로직을 람다로 표현하면 오히려 가독성이 떨어질 수 있습니다
결론
함수형 인터페이스는 자바의 함수형 프로그래밍을 가능하게 하는 핵심 요소입니다. 람다식과 함께 사용하면 더 간결하고 읽기 쉬운 코드를 작성할 수 있으며, 스트림 API와 결합하여 강력한 데이터 처리 기능을 구현할 수 있습니다.
적절한 상황에서 함수형 인터페이스를 활용하면 코드의 가독성과 유지보수성을 크게 향상시킬 수 있습니다. 특히 자바 8 이상을 사용하는 프로젝트에서는 필수적으로 알아야 할 개념이라고 할 수 있습니다.
'공부방 > JAVA' 카테고리의 다른 글
[이것이자바다] chapter 1. 자바 시작하기 (0) | 2023.04.18 |
---|---|
[모던 자바 인 액션] chapter 1. 자바 8, 9, 10, 11??? (0) | 2023.02.17 |
JAVA::파일의 수정 날짜 확인하기 (0) | 2022.08.25 |
JAVA::JVM에 대한 이해 (0) | 2021.12.22 |
JAVA::자바에서 형변환(Casting)하기 (0) | 2021.11.26 |