티스토리 뷰

Java

[Java] 메서드 참조 (method reference)

Jaehee Jeon 2022. 10. 28. 11:45
반응형

선수지식:  [Java] - 람다식(Lambda Expression)


메서드 참조란?

 메서드 참조(method reference)란 이미 존재하는 메서드 혹은 참조변수를 간결하게 지칭하는 방법이다. 람다식이 하나의 메서드만 호출하는 경우 그 식을 더 간결하게 나타내는 데에 쓰이며, 스트림 연산에서 빈번하게 사용된다. 이렇게 사용된 메서드 참조는 컴파일 단계에서 컴파일러가 알아서 람다식을 생성하여 처리된다.

 

 

사용법

 람다식은 매개변수와 함수 몸체를 화살표(->)로 이어 구성했다면, 메서드 참조는 매개변수와 화살표, 소괄호를 제거하고 아래와 같이 쓴다.

클래스명(혹은 참조변수명)::메소드명

 

예시

1.  Math.pow()

 아래와 같이 Math.pow() 메서드의 람다식을 메서드 참조로 변형하여 사용 가능하다. pow()의 경우 두 개의 double형 매개변수를 받아 double형 결과를 내놓으므로, 기본 제공되는 함수형 인터페이스 중 ToDoubleBiFunction을 사용 가능하다.

ToDoubleBiFunction<Double, Double> function;

function = (a, b) -> Math.pow(a, b);
System.out.println(function.applyAsDouble(5.0, 2.0)); // 25

function = Math::pow;
System.out.println(function.applyAsDouble(5.0, 2.0)); // 25

 

2.  System.out.print(), 스트림의 모든 요소 출력

 같은 방법으로 System.out.print() 메서드도 메서드 참조로 변형 가능하다. 매개변수를 받고 리턴값이 없는 기본 제공 함수형 인터페이스 Consumer<T>를 사용 가능하다.

Consumer<String> consumer;

consumer = (a) -> System.out.print(a);
consumer.accept("print"); // print

consumer = System.out::print;
consumer.accept("print\n"); // print

 

 물론 위와 같이 직접 함수형 인터페이스의 구현체를 만드는 대신, 아래와 같이 메서드 참조는 스트림을 통해 많이 사용된다.

List<Integer> intList = List.of(1,2,3);
Stream<Integer> intStream = intList.stream();

intStream.forEach(System.out::print); // 123

 

Stream.class의 최종 연산인 forEach()를 살펴보면 Consumer를 입력으로 받기 때문임을 알 수 있다.

 

 

 

3.  생성자 참조

 

 생성자의 호출도 람다식으로 표현할 수 있으므로, 이것을 다시 메서드 참조를 사용해 간결하게 만들 수 있다.

// 위 아래가 같은 의미
() -> new Object
Object::new // 클래스명::new

 

 

4. Stream에 메서드 참조 사용하기

 

 간단히 점수 class를 생성하고 리스트에 객체들을 담아 100점을 초과하는 점수 객체를 찾는다. 해당 객체를 찾지 못하면 IllegalArgumentException을 발생시킨다. 아래와 같이 Stream에 람다식만을 사용하여 적을 수 있다.

void test() {
    List<Score> scores = new ArrayList<>();
    scores.add(new Score(100));
    scores.add(new Score(120));
    Score score = scores.stream()
    	.filter(s -> s.over100())
        .findFirst()
        .orElseThrow(() -> new IllegalArgumentException());
}

class Score {
    int score;
    public Score(int score) {
    	this.score = score;
    }
    public boolean over100() {
        return this.score>100;
    }
}

 

 위의 Stream에 사용된 두 람다식이 파라미터 없이 하나의 메서드만 호출하므로 아래와 같이 메서드 참조를 사용하도록 변경 가능하다. (클래스 명::메서드 명)의 형태로 메서드인 over100과 Exception의 생성자를 참조한다.

 

void test() {
    List<Score> scores = new ArrayList<>();
    scores.add(new Score(100));
    scores.add(new Score(120));
    Score score = scores.stream()
    	.filter(Score::over100)
        .findFirst()
        .orElseThrow(IllegalArgumentException::new);
}

 

반응형