공공부하자개발 · 영어 학습 노트
자바
고급모던 자바와 성능0/10 완료
  • 01제네릭과 와일드카드
  • 02멀티스레드와 동기화
  • 03람다식과 함수형 인터페이스
  • 04Stream API와 병렬 처리
  • 05Optional로 NPE 방지
  • 06메서드 활용 패턴 (고급)
  • 07Java 21 모던 문법
  • 08어노테이션·리플렉션·동적 프록시
  • 09CompletableFuture 심화와 가상 스레드 실전
  • 10JVM 메모리·GC·OOM 진단
사이트 소개개인정보처리방침연락처
© 2026 공부하자
홈 › 고급 › 06 / 10

메서드 활용 패턴 (고급)

섹션 6진행 0 / 10
1왜 배우는가2핵심 원리3패턴 모음4자주 하는 실수 (Tip)5연습 문제6정리‹ 이전다음 ›

2. 핵심 원리

2.1 메서드 참조 4종

종류 문법 같은 뜻의 람다 예
static 메서드 클래스::메서드 x -> 클래스.메서드(x) Integer::parseInt
특정 객체의 인스턴스 메서드 객체::메서드 x -> 객체.메서드(x) prefix::concat, System.out::println
임의 객체의 인스턴스 메서드 클래스::메서드 x -> x.메서드() String::length, String::toUpperCase
생성자 클래스::new () -> new 클래스() ArrayList::new

1번과 3번은 문법이 같아서(클래스::메서드) 헷갈립니다. 구분은 메서드가 static인가입니다. Integer::parseInt는 static이라 첫 인자가 매개변수로, String::length는 인스턴스 메서드라 첫 인자가 수신 객체(this)가 됩니다. String::compareTo처럼 인자가 둘이면 (a, b) -> a.compareTo(b)입니다.

2.2 고차 함수(higher-order function)

함수를 인자로 받거나 함수를 반환하는 메서드입니다. 자바에서는 함수형 인터페이스 타입의 매개변수·반환 타입으로 표현합니다.

방향 시그니처 예 용도
받기 T applyTwice(UnaryOperator<T> f, T x) 전략 주입, 콜백, 파이프라인 단계
반환 IntUnaryOperator adder(int n) 팩토리, 커링, 부분 적용
받고 반환 Supplier<T> retry(int n, Supplier<T> action) 데코레이터(재시도, 캐시, 로깅, 시간 측정)

함수를 반환할 때 람다는 바깥 메서드의 매개변수(n)를 캡처합니다. 메서드가 끝나 스택 프레임이 사라져도 람다는 값을 복사해 갖고 있으므로(effectively final 제약이 여기서 나옵니다) adder(5)가 돌려준 함수는 언제 불러도 5를 더합니다.

2.3 함수 합성의 방향

java
f.andThen(g)  = x -> g(f(x))      // f 먼저, 그다음 g   (읽는 순서 = 실행 순서)
f.compose(g)  = x -> f(g(x))      // g 먼저, 그다음 f   (수학의 f∘g)

andThen이 왼쪽에서 오른쪽으로 읽히므로 실무에서는 거의 andThen만 씁니다. Predicate는 and/or/negate, Comparator는 thenComparing/reversed가 같은 역할입니다.

2.4 커링과 부분 적용

용어 뜻 형태
커링(currying) 인자 n개 함수를 "인자 1개를 받아 나머지를 받는 함수를 돌려주는" 함수로 변환 (a, b) -> c → a -> (b -> c)
부분 적용(partial application) 인자 일부를 미리 고정한 새 함수 (a, b) -> c, a=3 → b -> c

자바에는 내장 커링이 없지만 Function<A, Function<B, C>>로 표현합니다. 실무에서는 "설정값을 미리 묶은 함수"(partial(greet, "Hello"))로 자주 쓰입니다. 람다 문법에서 a -> b -> f.apply(a, b)는 a -> (b -> f.apply(a, b))로 오른쪽부터 묶입니다.

2.5 제네릭 메서드와 타입 추론

java
static <T> T firstOr(List<T> list, T fallback)
//     └ 타입 매개변수 선언: 반환 타입 앞

컴파일러는 인자의 타입과 대입되는 변수의 타입(target typing)에서 T를 추론합니다. 추론이 실패하는 경우(인자가 없고 대입도 없을 때, 람다 인자만 있을 때)는 Main.<String>emptyOf()처럼 점 앞에 타입 인자를 명시합니다. 이 문법은 반드시 클래스. 또는 this.가 앞에 있어야 합니다.

2.6 지연 평가(lazy evaluation)와 Supplier

valueOrDefault(v, expensive())는 v가 있어도 expensive()가 먼저 실행됩니다(인자는 호출 전에 평가). valueOrDefault(v, () -> expensive())는 필요할 때만 get()을 부릅니다. Optional.orElse vs orElseGet, 로깅의 log.debug(() -> ...), Stream의 중간 연산이 모두 같은 원리입니다.

2.7 CompletableFuture 체이닝 3종

메서드 인자 함수의 형태 언제
thenApply(f) T -> U 결과를 동기 변환 (map)
thenCompose(f) T -> CompletableFuture<U> 결과로 또 다른 비동기 작업 시작 (flatMap)
thenCombine(other, f) (T, U) -> V 독립된 두 작업이 모두 끝나면 합치기

thenApply에 CompletableFuture를 돌려주는 함수를 넣으면 CompletableFuture<CompletableFuture<U>>가 됩니다. 그것을 펴 주는 것이 thenCompose입니다. Optional.map/flatMap, Stream.map/flatMap과 정확히 같은 구분입니다.

핵심 원리
  • 2.1 메서드 참조 4종
  • 2.2 고차 함수(higher-order function)
  • 2.3 함수 합성의 방향
  • 2.4 커링과 부분 적용
  • 2.5 제네릭 메서드와 타입 추론
  • 2.6 지연 평가(lazy evaluation)와 Supplier
  • 2.7 CompletableFuture 체이닝 3종
이전 섹션1 왜 배우는가2 / 6다음 섹션3 패턴 모음