Java

[모던 자바] Java 8 메서드 참조와 생성자 참조란?

Beekei 2022. 3. 2. 12:36
반응형

메서드 참조란?

메서드 참조는 특정 람다의 축약형이라고 생각할 수 있다.

메서드 참조를 이용하면 기존 메서드 정의를 재활용해서 람다처럼 전달할 수 있으며 때로는 람다 표현식보다 메서드 참조를 사용하는 것이 더 가독성이 좋으며 자연스러울 수 있다.

inventory.sort((Apple a1, Apple a2) -> a1.getWeight().compareTo(a2.getWeight())); // 람다 표현식
inventory.sort(compareTo(Apple::getWeight)); // 메서드 참조

위 코드를 보면 Apple::getWeight는 Apple에 정의된 getWeight의 메서드 참조다. 메서드명 앞에 구분자(::)를 분해 방식으로 메서드 참조를 활용하였다.

 

메서드 참조를 이용하면 같은 기능을 더 간결하게 구현할 수 있어서 가독성을 높일 수 있다. 

메서드 참조를 새로운 기능이 아니라 하나의 메서드를 참조하는 람다를 편리하게 표현할 수 있는 문법으로 간주하면 되겠다.


메서드 참조를 만드는 방법

메서드 참조는 세 가지 유형으로 구분할 수 있다.

1. 정적 메서드 참조

// 람다 표현식
ToIntFunction<String> stringToInt = (String s) -> Integer.parseInt(s);
// 메서드 참조
Function<String, Integer> stringToInteger = Integer::parseInt;

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

// 람다 표현식
BigPredicate<List<String>, String> contains = (list, element) -> list.contains(element);
// 메서드 참조
BigPredicate<List<String>, String> contains = List::contains;

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

// 람다 표현식
Predicate<String> startsWithNumber = (String s) -> this.startsWithNumber(s);
// 메서드 참조
Predicate<String> startsWithNumber = this::startsWithNumber;

이 유형은 비공개 헬퍼 메서드를 정의한 상황에서 유용하게 활용할 수 있다.


생성자 참조란?

ClassName::new 처럼 클래스명과 new 키워드를 이용해서 기존 생성자의 참조를 만들 수 있다. 이것은 정적 메서드의 참조를 만드는 방법과 비슷하다. 아래는 여래 색상의 자동차를 만드는 예제 코드이다.

@ToString
@AllArgsConstructor
public class Car {
    private String color;
}

public List<Car> map(List<String> list, Function<String, Car> f) {
    List<Car> results = new ArrayList<>();
    for(String s:list) {
        results.add(f.apply(s));
    }
    return results;
}

List<String> colors = Arrays.asList("Gray", "Black", "White");
List<Car> cars = map(colors, Car::new); // map 메서드로 생성자 참조 전달
// [Car{color='Gray'}, Car{color='Black'}, Car{color='White'}]

만약 인수가 두 개라면 BiFunction을 사용하면 되고 세 개라면 TriFunction을 사용하면 된다.

@ToString
@AllArgsConstructor
public class Car {
    private String color;
    private Integer price;
}

public List<Car> map(Map<String, Integer> map, BiFunction<String, Integer, Car> f) {
    List<Car> results = new ArrayList<>();
    for (String color : map.keySet()) {
        results.add(f.apply(color, map.get(color)));
    }
    return results;
}

Map<String, Integer> carInfos = new HashMap<>() {{ 
    put("Gray", 30000000); 
    put("White", 31000000); 
    put("Black", 32000000); 
}};
List<Car> cars = map(carInfos, Car::new); // map 메서드로 생성자 참조 전달
// [Car{color='Gray', price='30000000'}, Car{color='White', price='31000000'}, Car{color='Black', price='32000000'}]

 

 

정리해보자면,
동작 파라미터화람다 표현식을 사용해 가독성 좋게 구현하고, 이 람다 표현식을 메소드 참조와 생성자 참조를 사용하여
조금 더 가독성 좋게 코드를 구현할 수 있다. 
반응형