메소드 레퍼런스란?

Bruce Han·2023년 2월 10일
1

Java8-정리

목록 보기
4/20
post-thumbnail
post-custom-banner

이 포스팅의 코드 및 정보들은 강의를 들으며 정리한 내용을 토대로 작성한 것입니다.

메소드 레퍼런스란

람다 표현식을 구현할 때, 기존에 이미 있는 메서드를 참조하는 것. 즉, 그 메서드 자체를 Functional Interface의 구현체로 쓰게 되는 것이다.

문자열을 하나 넣어서 문자열을 받고자 하는

static 메서드 참조

method-reference

먼저 실습에 앞서 클래스와 메서드를 만들어놨다.

이를 구현하기 위해 Function<String, String>을 사용할 수 있고, 입력값과 반환값이 같은 경우에는 UnaryOperator<String>으로 줄여서 활용할 수 있다.

UnaryOperator<String> hola = (s) -> "hola " + s;

이 람다식이 하는 일은

method-reference2

Greeting 클래스에서 만든 Hola라는 static 메서드와 같다.
또한, static 메서드를 람다식에서 사용할 수도 있다.

method-reference3

즉, UnaryOperator의 구현체로 static 메서드를 사용하겠다는 것이다.
::(콜론 두 개)를 이용해서 메서드를 호출하는 것을 메서드 레퍼런스라고 한다.

Type::staticMethodName 이런 식으로 참조하면 된다.

특정 객체의 인스턴스 메서드 참조

특정한 인스턴스의 메서드를 사용하는, 즉 클래스 안에 들어있는 인스턴스 메서드를 사용하는 방법도 있다.

method-reference4

생성자를 호출할 때 리턴값은 객체의 타입이다.

입력값은 없는데 결과값은 있는 것. -> Supplier 인터페이스로 알아보겠다.

method-reference5

이렇게 생성만 해놓고 보면 아무 일도 일어나지 않는다. 이 자체로 새로운 인스턴스를 만드는 것은 아니다.

public static void main(String[] args) {
    Supplier<Greeting> newGreeting = Greeting::new;
    Greeting greeting = newGreeting.get();
}

Supplier 인터페이스에 있는 get()을 통해서 인스턴스를 만들 수 있다.

public static void main(String[] args) {
    Greeting greeting = new Greeting();
    UnaryOperator<String> hallo = greeting::hallo;
}

이 메서드를 참조하고 있는 UnaryOperator가 만들어진 것이지, 이 자체로는 인스턴스가 생성됐다고 볼 수 없다.

hallo.apply("bruce") 이런식으로 apply()를 통해서 새 인스턴스를 만들 수 있는 것이다.

method-reference6

apply를 통해서 bruce라는 값이 greeting이라는 인스턴스에 있는 hallo 메서드에 전달되고, 이반환 값을 가져와서 문자열이 출력된 것을 확인할 수 있다.

생성자 참조

public Greeting(String name) {
    this.name = name;
}

이런 생성자는 입력 값은 String, 반환 값은 Greeting이 된다.

method-reference7

Function 인터페이스와 Supplier 인터페이스는 같은 생성자를 쓰는 것 같지만, 서로 다른 생성자를 참조한다.

Function을 먼저 알아보면

public Greeting(String name) {
    this.name = name;
}

Function 인터페이스는 문자열을 받는 생성자를 참조하고 있고

method-reference8

apply()에 bruce를 넣어서 이를 출력한 것을 확인할 수 있다.

public Greeting() {}

반면에 Supplier는 문자열을 받지 않는 생성자를 참조하고 있다.

method-reference9

아무 이름도 부여하지 않은 채 getName()으로 이름을 반환하면 당연히 null이 출력된다.
Supplier 인터페이스를 통해서는 hallo() 메서드를 이용하여 이름을 출력한 것을 확인할 수 있다.

임의 객체의 인스턴스 메서드 참조

불특정 다수인 인스턴스의 특정 인스턴스 메서드를 참조하는 방법이다.

public static void main(String[] args) {
    String[] names = {"bruce", "minsu", "spring"};
    Arrays.sort(names, new Comparator<String>() {
        @Override
        public int compare(String o1, String o2) {
            return 0;
        }
    });
}

Arrays.sort의 두 번째 파라미터가 Comparator<>() {}인 함수형 인터페이스이기 때문에, 이 자리에다가 람다를 넣을 수 있다.

Arrays.sort(names, (o1, o2) -> 0);

람다를 넣을 수 있다는 얘기는 메서드 레퍼런스를 쓸 수 있다는 것이다. 즉, 어떤 문자열이 다른 문자열하고 비교해서 int값을 넘겨주는 메서드를 참조할 수 있다.

method-reference10

String 클래스의 compareToIgnoreCase()로 실습을 해보겠다.
compareToIgnoreCase()는 자기자신의 문자열과 파라미터로 받은 문자열을 비교해서 int type을 넘겨준다.

public static void main(String[] args) {
    String[] names = {"bruce", "minsu", "cheolsu"};
    Arrays.sort(names, String::compareToIgnoreCase);
}

bruce가 (파라미터로 넘겨질) 뒤에 오는 minsu와 compareToIgnoreCase()로 비교해서 int 값을 반환하게 된다. 마찬가지로 minsu가 cheolsu랑 비교해서 int값을 리턴하는 식으로 동작하게 될 것이다.

String::compareToIgnoreCase에다가 준 메서드 레퍼런스는 "bruce", "minsu", "cheolsu" 처럼 임의의 인스턴스를 거쳐가면서 compareToIgnoreCase라는 인스턴스 메서드를 사용하게 되는 것이다.

method-reference11

Arrays.toString(names)을 통해서 이름들이 정렬된 것을 확인할 수 있다.

Reference

profile
만 가지 발차기를 한 번씩 연습하는 사람은 두렵지 않다. 내가 두려워 하는 사람은 한 가지 발차기를 만 번씩 연습하는 사람이다. - Bruce Lee
post-custom-banner

0개의 댓글