본문 바로가기

TIL

이중콜론(::)(매서드 참조)표현식

다른 팀원들과 코드 리뷰 해보던 중 팀원 코드에서

 Double::sum

이런 식의 코드를 발견하였다. 이게 뭔지 여쭤보니 AI랑 블로그 짬뽕해서 만들어서 정확히 모르겠다 하셔서 이게 뭔지 조금 더 공부를 해보았습니다.

 

인단 문법은

인스턴스명::메서드명

위와 같은 표현방식을 이용한다고 합니다.

사실 이게 뭐냐면 우리가 람다식을 사용할때

(a, b) -> calculate.sum(a, b);

이런식으료 표현을 하는데 이를 sum으로 보내는 매개 변수를 이미 이전 결과에서 알고 있고 똑같은 행위가 map이나 forEach등에서 반복적으로 사용될때 사용한다고 합니다.

 

즉,

calculate::sum

이런식으로 작성하면 이전에 받은 결과들을 sum함수에 매개변수로 전달을 해준다는 의미 라고 이해했습니다.

적용 전 --
stream.map(x -> Integer.parseInt(x))
적용 후 --
stream.map(Integer::parseInt)

이걸를 다른 식으로 사용하면 생성자의 참조도 쉽게 만들 수있는데 

적용 전 --
User::new
적용 후 --
() -> new User()
name -> new User(name)

이런식으로 객체를 만들때도 활용 할 수 있다고 합니다.

 

그러면 제가 만든 코드를 이런식으로 선언 할 수 있을까??

Calculator<Double> calculator = Calculator::new;

아니라고 합니다 에러를 보면 

함수형 인터페이스가 아니라고 하는데...

 

그럼 함수형 인터페이스는 뭐지??

메서드가 딱 하나만 있는 인터페이스

라고 지금 당장은 이해했습니다. 

interface MyFunc {
    int run(int x);
}

근데 이걸 사용해서 어떻게 메서드 참조를 만드느냐??

이 부분이 진짜 어려운 부분인거같은데(완벽히 이해하지 못했음)

예를 들어서 저런 인터페이스가 있고,

class Cal {
    public int square(int x){
    	return x * x;
    }
}

이런 클래스가 있다고생각해 봅시다.

그럼 이걸 이제

MyFunc f = x -> new Cal().square(x);

Cal cal = new Cal();
MyFunc f = cal::square;

이런식으로 만들어 쓸 수 있습니다.

즉, class (객체)를 :: 메서드 참조를 이용해서 선언 해줄 수 없고, 대신

메서드 참조를 활용해 기존에 있던 객체를 함수형 인터페이스로 만들 수 있습니다. 

Cal cal = Cal::new -> (X) 불가
//하지만
myFunc f = cal::square
// 함수형 인터페이스를 선언 할 때 사용할 수 있음

 

더보기

그러면 왜 굳이 함수형 인터페이스를 타입으로 선언할까? 라는 의문을 가졌는데,

"값" 을 저장하는게 목적이 아닌 "행동(로직)" 을 저장하기 위한 타입이라고 합니다. 

아직까지 이걸 어디에 쓸 수 있을지는 잘 모르겠지만, 지나고 보면 알 수 있을거라 생각이 듭니다

여기서 드는 의문은 아니 class가 interface를 impl을 안해줬는데 어케 저게 타입이 일치하는가? 하는 의문이었는데 이는 

두 클래스와 함수형인터페이스를 람다가 "이 메서드의 모양이 인터페이스의 메서드 모양가 같나?" 만 확인하기 때문입니다. 

즉 cal.square의 모양 public int square(int x){return int} 이 인터페이스의 int run(int x) 모양과 완전히 동일하기 때문입니다.

 

주저리 주저리 말이 많았는데 일단 지금 이해해야 할 부분은 매서드참조는 이런식으로 람다에서 사용할 수 있고 이런 특징이 있구나 대략적으로 알아가면 좋을거같습니다.

 

추가적으로 어제 팀원분 코드중에 이런코드가 있었는데

 private final Function<Double, T> resultConverter;

근데 공부를 하다보니 여기까지 연결 되어있는 것을 알 수 있었는데 저 Function이 바로 함수형 인터페이스 인것입니다.

Function<T,R>은 자바가 이미 만들어 둔 함수형 인터페이스이며, Function.apply(T t)은 타입 T를 R로 변환해주는 함수입니다.