본문 바로가기
language/java

Java Method Reference(::) 완벽 이해하기

by 죄니안죄니 2026. 5. 28.
반응형

Java Method Reference(::) 완벽 이해하기

Java Stream과 Lambda를 공부하다 보면 정말 자주 보게 되는 문법이 바로:

 
::
 

입니다.

대표적으로:

 
System.out::println
 

같은 코드.

처음 보면:

“이거 왜 쓰는 거지?”
 

싶기 쉽습니다.

하지만 Method Reference는 단순 축약 문법이 아니라:

  • Lambda
  • 함수형 인터페이스
  • Stream API
  • JVM method handle
  • 생성자 참조(Constructor Reference)

까지 연결되는 중요한 기능입니다.

이번 글에서는:

  • Method Reference란?
  • 람다와 차이
  • 종류 4가지
  • static/instance reference
  • 생성자 참조
  • 실무 사용 패턴
  • JVM 내부 동작

까지 깊게 정리해보겠습니다.


1. Method Reference란?

Method reference 는:

기존 메서드를 람다처럼 전달하는 문법

입니다.


2. 가장 기본 예시

 
x -> System.out.println(x)
 

 
System.out::println
 

축약 가능.


3. 왜 등장했을까?

람다도 간단하지만:

 
x -> someMethod(x)
 

처럼:

“전달만 하는 람다”
 

가 너무 많았기 때문.


4. 핵심 아이디어

즉:

“메서드 자체를 값처럼 전달”
 

하는 것.


5. Method Reference는 언제 가능할까?

매우 중요.

다음 형태일 때만 가능.


기존 람다

 
x -> method(x)
 

Method Reference

 
ClassName::method
 

즉:

단순 전달 형태
 

일 때 가능.


6. 대표 예시

 
list.forEach(System.out::println);
 

7. 실제 타입은?

여기서:

 
System.out::println
 

은 실제로:

Consumer<T>
 

구현체.


8. 람다와 동일한 의미

즉:

 
x -> System.out.println(x)
 

와 동일.


9. Method Reference 종류

매우 중요.

총 4가지 대표 형태 존재.


10. ① Static Method Reference

형태:

 
ClassName::staticMethod
 

11. 예시

 
Integer::parseInt
 

12. 람다로 풀면

 
s -> Integer.parseInt(s)
 

13. Stream 예시

 
list.stream()
    .map(Integer::parseInt)
 

14. ② 특정 객체의 Instance Method Reference

형태:

 
object::instanceMethod
 

15. 예시

 
PrintStream out = System.out;

Consumer<String> c =
    out::println;
 

16. 람다로 풀면

 
s -> out.println(s)
 

17. ③ 임의 객체의 Instance Method Reference

가장 헷갈리는 유형.


18. 형태

 
ClassName::instanceMethod
 

19. 예시

 
String::toUpperCase
 

20. 람다로 풀면

 
s -> s.toUpperCase()
 

21. 왜 가능할까?

첫 번째 파라미터가:

메서드 호출 대상 객체
 

로 사용되기 때문.


22. 매우 중요한 예시

 
list.stream()
    .map(String::length)
 

23. 실제 의미

 
s -> s.length()
 

24. ④ Constructor Reference

매우 중요.


25. 형태

 
ClassName::new
 

26. 예시

 
Supplier<User> s =
    User::new;
 

27. 람다로 풀면

 
() -> new User()
 

28. 생성자 파라미터도 가능

 
Function<String, User> f =
    User::new;
 

29. 의미

 
name -> new User(name)
 

30. 배열 생성도 가능

 
IntFunction<int[]> f =
    int[]::new;
 

31. Method Reference와 함수형 인터페이스

매우 중요.

Method Reference는 반드시:

함수형 인터페이스 문맥
 

필요.


32. 예시

 
Function<String, Integer> f =
    Integer::parseInt;
 

컴파일러가:

어떤 메서드와 매핑할지 추론
 

합니다.


33. Method Overloading 주의

매우 중요.

예:

 
println(...)
 

오버로딩 매우 많음.


34. 그런데 왜 동작할까?

컴파일러가:

함수형 인터페이스 시그니처
 

기반으로 적절한 메서드 선택.


35. JVM 내부 동작

람다와 동일하게 대부분:

invokedynamic
 

기반 처리.


36. Method Handle 사용

Method handle 기반으로:

메서드 참조 연결
 

수행.


37. 왜 중요한가?

JVM이:

  • lazy linking
  • 최적화
  • inline

하기 더 유리.


38. 람다 vs Method Reference


항목 람다 Method Reference
표현력 자유로움 단순 전달 특화
가독성 상황 따라 다름 간결
복잡 로직 가능 불가능

39. Method Reference가 항상 좋은 건 아니다

매우 중요.


40. 안 좋은 예

 
.map(UserService::convertAndValidateAndNormalize)
 

너무 길고 의미 불명확 가능.


41. 오히려 람다가 더 나을 수도

 
.map(user -> normalize(user))
 

더 읽기 쉬운 경우 많음.


42. Stream API에서 매우 많이 사용

대표:

 
.map(User::getName)
.filter(String::isBlank)
.forEach(System.out::println)
 

43. Comparator와도 연결

 
Comparator.comparing(User::getAge)
 

44. Optional과도 연결

 
optional.ifPresent(System.out::println)
 

45. 실무에서 자주 하는 실수

1) Method Reference 남용

오히려 가독성 저하 가능.


2) 임의 객체 instance reference 이해 부족

 
String::length
 

헷갈리기 쉬움.


3) 오버로딩 충돌

컴파일러 추론 실패 가능.


4) 람다와 Method Reference 차이 오해

Method Reference는 “단순 전달” 전용.


46. 핵심 흐름 요약

람다 표현식
↓
단순 메서드 호출 형태
↓
Method Reference(::)로 축약 가능
 

47. 종류 정리


종류 예시
static method Integer::parseInt
특정 객체 method out::println
임의 객체 method String::length
constructor User::new

48. 가장 중요한 핵심 한 줄

Method Reference는
“기존 메서드를 함수형 인터페이스 구현처럼 전달하는 문법”
 

입니다.


49. 정리

Method Reference는 단순 축약 문법이 아닙니다.

실제로는:

  • Lambda
  • 함수형 인터페이스
  • Stream API
  • Constructor Reference
  • JVM invokedynamic

전체와 연결되는 Java 함수형 프로그래밍 핵심 기능입니다.

특히 실무에서는:

  • Stream map/filter
  • Comparator.comparing
  • 생성자 참조
  • 오버로딩 추론
  • 가독성 기준

을 정확히 이해하는 것이 매우 중요합니다.

다음 글에서는:

Collector 활용

을 Collectors.toList(), groupingBy(), partitioningBy(), downstream collector, 병렬 수집 구조까지 포함해서 깊게 정리해보겠습니다.

반응형

댓글