메서드 참조
이제 람다 표현식에 이어 메서드 참조에 대해 알아보자.
메서드 참조를 이용해 기존의 메서드 정의를 재활용해서 람다처럼 전달할 수 있다.
때로는 람다 표현식보다 메서드 참조를 사용하는 것이 더 가독성이 좋으며 자연스러울 수 있다.
다음은 메서드 참조와 새로운 자바8 API를 이용한 정렬 예시다.
//기존 코드
inventory.sort((Apple a1, Apple a2) -> a1.getWeight().compareTo(a2.getWeight())));
//다음은 메서드 참조와 java.util.Comparator.comparing을 활용한 코드다.
inventory.sort(comparing(Apple::getWeight)); //이제부터 이 문법에 대해 알아보자.
메서드 참조는 특정 메서드만을 호출하는 람다의 축약형이라고 생각할 수 있다.
예를 들어 람다가 '이 메서들르 직접 호출해'라고 명령한다면 메서드를 어떻게 호출해야 하는지 설명을 참조하기보다는
메서드명을 직접 참조하는 것이 편리하다.
실제로 메서드 참조를 이용하면 기존 메서드 구현으로 람다 표현식을 만들 수 있다.
이때 명시적으로 메서드명을 참조함으로써 가독성을 높일 수 있다.
메서드명 앞에 구분자(::)를 붙이는 방식으로 메서드 참조를 활용할 수 있다.
이제 아래 예시들을 살펴보자.
람다 | 메서드 참조 단축 표현 |
(Apple apple) -> apple.getWeight() | Apple::getWeight |
() -> Thread.currentThread().dumpStack() | Thread.currentThread::dumpStack |
(str, i) -> str.substring(i) | String::substring |
(String s) -> System.out.println(s) | System.out::println |
(String s) -> this.isValidName(s) | this::isValidName |
메서드 참조를 새로운 기능이 아니라 하나의 메서드를 참조하는 람다를 편리하게 표현할 수 있는 문법으로 간주할 수 있다.
메서드 참조를 이용하면 같은 기능을 더 간결하게 구현할 수 있다.
메서드 참조를 만드는 방법
메서드 참조는 세 가지 유형으로 구분할 수 있다.
- 정적 메소드 참조
예를 들어 Integer의 parseInt 메서드는 Integer::parseInt로 표현할 수 있다. - 다양한 형식의 인스턴스 메서드 참조
예를 들어 String의 length 메서드는 String::length로 표현할 수 있다. - 기존 객체의 인스턴스 메서드 참조
예를 들어 Transaction 객체를 할당받은 expensiveTransaction 지역 변수가 있고,
Transaction 객체에는 getValue 메서드가 있다면, 이를 expensiveTransaction::getValue라고 표현할 수 있다.
세 번째 유형의 방식이 유독 이해가 가지 않았다.
이 유형의 메서드 참조는 람다 표현식에서 현존하는 외부 객체의 메서드를 호출할 때 사용된다.
예를 들어 expensiveTransaction.getValue()라는 람다 표현식을 expensiveTransaction::getValue로 줄여서 표현할 수 있다.
컴파일러는 람다 표현식의 형식을 검사하던 방식과 비슷한 과정으로 메서드 참조가 주어진 함수형 인터페이스와 호환하는지 확인한다.
즉, 메서드 참조는 콘텍스트의 형식과 일치해야 한다.
참고 문헌
모던 자바 인 액션 (라울-게이브리얼 우르마) - 3장 람다 표현식
댓글