본문 바로가기
Back-End/Java

TIL 230712 : 자바의 람다식 짚고 넘어가기(2) 메소드 참조

by 우인입니다 2023. 7. 13.

https://thiswooin.tistory.com/50

 

TIL 230711 : 자바의 람다식 짚고 넘어가기.

조금은 머쓱한 얘기지만 자바의 기본 문법을 배울 때 잘 이해되지 않고 다른 것들에 밀려 유보해두었던 람다와 스트림에 대해 다시 한 번 공부를 해서 개념을 짚고 넘어가보려 합니다. 강의를

thiswooin.tistory.com

지난 시간 이어서 메소드 참조에 대해서도 정리해보려 한다.

 


메소드 참조

Page<ProductResponseDto> responseDtoList = products.map(ProductResponseDto::new);

위 코드에서 맨마지막 부분이 의문이었다.

모던자바 문법 중 하나로 메소드 참조라는 문법이다.

 

예시

 

(left, right) -> Math.max(left,right);

위와 같은 람다식에서 Math.max는 매개변수를 전달만 하는 역할을 한다. 이럴 때 람다식에서 불필요한 매개변수를 제거하는 것을 목적으로 한다.

 

Math::max;

위와 같이 축약하여 표현해준다.

 

 

예시2

함수형 인터페이스와 그 객체를 매개변수로 갖는 메소드 설정

함수형 인터페이스

@FunctionalInterface
public interface Calcuable {
	double calc(double x, double y);
}

여기 실천에 옮기지는 못 하고 그럴싸한 계획(입력, 출력 타입)만 갖고 있는 함수형 인터페이스가 있습니다.

 

 

클래스와 메소드(인터페이스를 매개변수로 갖음)

public class Person {
	public void action(Calcuable calcuable) {
    	double result = calcuable.calc(10, 4);
        System.out.printLn("결과: " + result);
    }
}

Person클래스에서 Calcuable 타입을 매개변수로 받는 action메소드가 있습니다.

action메소드 안에는 Calcuable의 메소드 calc에 매개변수로 10,4를 넣어 result에 할당해주는 코드가 있습니다.

 

이제 Person의 객체를 생성해 action메소드를 실행할 준비를 해보겠습니다.

 

 

실행문

public class Prac {

	public static void main(String[] args) {
    
    	Person person = new Person();
        
        person.action( @@@ );
    
    }
}

 

action의 @@@에는 Calcuable의 객체가 들어가야합니다.

 

Person person = new Person();

Calcuable calcuable = new Calcuable() {
    @Override
    public double calc(double x, double y);
    return x + y;
}

person.action( calcuable );

위처럼 Calcuable 인터페이스의 익명객체를 만들때 인터페이스에 있던 메소드를 오버라이드해서 생성을하고

이를 action메소드의 매개변수로 넣어줍니다.

 

이 모양은 메소드가 하나인 함수형 인터페이스의 객체에 매개변수값과 실행문만 써줄 수 있는 람다식으로 아래와 같이 표현이 가능합니다.

 

Person person = new Person();

person.action( (x, y) -> { return x + y } );

'action의 매개변수인 Calcuable타입은 어차피 메소드가 하나다. 그리고 그 메소드를 구현해줘야하는데 그때 굳이 객체를 만들 필요가 없다.(실행만 되고 반환하고 끝인데) 그래서 그냥 저 안에서 한 큐에 바로 하나밖에 없는 Calcuable의 calc메소드를 만들어줘서 계산하는 느낌.'

 

위는 x + y 의 코드가 실행되는 메소드를 구현한 람다식이다.

만약 이 상황에서 메소드를 직접 구현하는 게 아니라 외부에 있는 메소드를 가져와서 쓴다면 아래처럼 쓸 수 있을 것이다.

 

우선 외부의 메소드를 하나 만들어봅니다.

public class Computer {
	public static double calcAdd(double x, double y) {
    	return x + y;
    }
}

 

그리고 이 메소드를 가져와 봅니다.

Person person = new Person();

person.action( (x, y) -> { return Computer.calcAdd(x, y) } );

+실행문이 return 한문장이라서 실행문을 감싸는 { } 의 간략한 축약이 가능합니다.

 

person.action( (x, y) -> Computer.calcAdd(x, y) );

이제 위 모양에서 x, y 를 받아서 그대로 Computer.calcAdd로 전달만하고 있는데, 이를 메소드를 참조한다는 의미로 아래와 같이 축약 가능합니다.

 

person.action( Computer::calcAdd );

'람다식의 실행문을 굳이 안 써주고 다른 메소드를 복붙해와 달라는 느낌의 메소드 참조같은 느낌.'

람다식의 실행문은 인터페이스의 하나밖에 없는 메소드였는데 그 메소드를 오버라이드 해주는 그런 느낌..

근데 그걸 다른 메소드로 대체해준다.

 


이제 뭔 말인지 설명을 보면 대략 알겠는데, 어떨때 깔쌈하게 활용해야할지는 더 공부가 필요해 보인다.

잘 짠 코드를 보고 해당 부분을 보면 '아! 이렇게 쓰면 좋구나'를 알 수 있을텐데.

 

편하기 위해 개발된 문법들이다.

자바 1.8이후의 변화에 우선 빨리 적응해야할 듯하다.