JAVA

[JAVA] 자바8 메서드 참조 (Method reference) 이중콜론 ::

딘딘은딘딘 2023. 9. 9. 17:24
반응형

* 메서드 참조란?

특정 메서드만을 호출하는 람다의 축약형이라고 볼 수 있다.

즉, 기존 메서든 구현으로 람다 표현식을 만들 수 있으며

이중콜론(::)을 사용해 명시적으로 메서드명을 참조함으로써 더 간결하게 가독성을 높일 수 있다.

 

 


* 메서드 참조 사용방법

메서드 참조의 유형은 4가지가 존재한다.

 

1. 정적 메서드 참조

   Ex) Integer의 parseInt 메서드는 정적(static) 메서드 이므로 바로 위 사진과 같이 Integer::parseInt 로 사용할 수 있다.

2. 다양한 형식의 인스턴스 메서드 참조

   Ex) String의 length() 메서드는 인스턴스 메서드로 다음과 같이 사용한다 

String a = "a";
IntSupplier i = a::length;
int num = i.getAsInt();

3. 기존 객체의 인스턴스 메서드 참조

   Ex) Integer의 parseInt 메서드는 정적(static) 메서드 이므로 Integer::parseInt 로 사용할 수 있다.

4. 생성자 참조

 

 

1. 정적 메서드 참조

대표적으로 java.lang 패키지의 Integer는 정적 메서드 parseInt를 참조해 사용할 수 있다.

 

이번에는 메서드 참조를 위한 함수형 인터페이스를 직접 만들어

테스트 하기 위해 두개의 정수형 파라미터를 받고 int를 반환하는 함수형 인터페이스를 생성해본다

 

함수형 인터페이스 FnInterFaceAdd를 생성

 

그리고 Integer의 parseInt와 같이 실제 동작을 하는 클래스와 두개의 수를 계산해주는 정적 메서드를 생성한다.

 

 

메서드 참조는 람다의 축약형이라고 했다.
람다의 경우 함수형 인터페이스를 타입으로 받을 수 있으며
메서드가 정의된 함수형 인터페이스를 통해 값을 할당 받게 된다.
그래서 새로운 메서드 참조를 사용하기 위해서는 함수형 인터페이스와 동작을 구현할 메서드 생성은 필수이다.

 

실행 결과

 

2. 인스턴스 메서드 참조

인스턴스 메서드는 

사용하고자 하는 메서드가 정의 되어있는 클래스 객체를 변수에 할당해

변수명(인스턴스).메서드 명을 통해 사용하는 메서드이다.

 

스태틱 메서드와 달리 변수를 직접 생성한 뒤 사용 해야하며 메모리에 저장되는 방식의 차이가 있다.

 

메서드 참조에서는 사용방식이 비슷하다.

먼저 비정적(non-static) 메서드 선언

 

먼저 객체 선언을 해준 뒤 같은 방식으로 참조를 사용하면 된다.

(역시 람다를 축약하는 방식이기 때문에 인텔리제이에서도 메서드 참조 방식을 사용하라고 추천을 해준다.)

 

3. 객체의 인스턴스 메서드 참조

자바 개발을 하다보면 객체를 사용자의 상황에 맞게 정의해서 사용하는 경우가 있다.

예를들어 MVC패턴에서 DTO클래스는 필드가 있고, getter / setter / 생성자 등 롬복의 @Data를 사용하는 경우가 있다.

( 필드와 메서드가 존재하는 DTO(클래스)를 생성 하면 Heap 영역에 저장되는데 이를 객체 라고 한다.)

 

정수형 데이터 가져오는 함수형 인터페이스를 새로 정의한다.

 

이후 객체를 생성해 god라는 변수에 할당한 후

가격을 가져오는 변수를 메서드 참조를 이용해 호출한다.

 

임의로 만든 함수형 인터페이스 FnInterFaceGetValue의 getNumber()은

파라미터가 존재하지 않으며 리턴 타입은 int이다.

이와 같은 형식은 롬복의 getter 메서드와 람다 시그니처가 일치한다.

 

God라는 객체의 getPrice는 파라미터가 존재하지 않으며 리턴 타입은 int이다.

따라서 FnInterFaceGetValue 를 타입으로 갖는 변수를 생성한 뒤 god::getPrice를 할 수 있다.

 

위와 같은 방식으로 실무에서 함수형 인터페이스를 잘 정의 한다면

메서드 참조나 람다를 다양하게 이용해 더 좋은 가독성을 가질 수 있을 것이다.

 

4. 생성자 참조

String::new와 같이 new 키워드를 이용해서 생성자의 참조를 만들 수 있다.

 

먼저 참고를 할만한 자바의 함수형 인터페이스 시그니처 표를 보자.

 

 

우선 인수가 없는 생성자와 Integer count를 인수로 받는 Apple라는 객체를 생성한다.

함수형 인터페이스 Supplier<T>의 시그니처는 T get()으로 파라미터를 받지 않으며

입력값 없이 제네릭 타입의 T만 리턴한다.

Supplier이 인수가 없는 생성자 참조에 사용될 것이다.

또 다른 함수형 인터페이스 Function<T, R>의 시그니처는 R apply(T t) 이며 값을 다른 값으로 변환해 R을 리턴한다.

Function은 인수가 하나인 생성자 참조에 사용될 것이다.

 

코드를 실행하면 아래와 같다.

위 예시는 인수가 0개, 1개인 시그니처를 가지고 있는 함수형 인터페이스를 사용한 예제이다.

자바 함수형 인터페이스 시그니처를 검색하면 다양한 표를 확인 할 수 있다.

참고 : (https://johngrib.github.io/wiki/java/functional-interface/)

 

추가로 생성자 참고를 응용하면 아래와 같이 사용할 수 있다.

Integer 리스트에 map 스트림을 사용해 Apple::new 생성자로 생성해 스트림에 할당 한뒤 리스트로 변환하면

List<Apple> 타입의 리스트에 할당할 수 있다. 

 


* 정리

- 메서드 참조는 특정 메서드만을 호출하는 람다의 축약형이다.

   즉 메서드 참조는 새로운 기능이 아니라 람다를 편리하고 간결하게 표현할 수 있는 문법이다.

 

- 메서드 참조 (람다)를 사용하기 위해서는 함수형 인터페이스를 반드시 생성 해야한다.

- 생성자 참조 및 객체의 인스턴스 메서드 참조는 잘 활용하면 실무에서 가독성이 더 좋아지도록 활용할 수 있다.

반응형