[Java] 람다식과 메소드 참조(Method references)
June 03, 2024
Java에서 람다식과 함께 메소드 참조 방식을 사용할 수 있습니다. 메소드 참조 방식은 람다식 대신에 사용할 수 있으며, 코드가 짧아서 구현이 간단합니다.
메소드 참조 방식에 대해서 알아보겠습니다.
1. 메소드 참조(Method References)
메소드 참조(Method References)는 람다식을 더 간단하고 가독성 있게 작성할 수 있게 해줍니다. 즉, 간단한 방법으로 람다식을 표현하는 것이 메소드 참조라고 할 수 있습니다.
- 주로 함수형 인터페이스를 사용할 때 사용됩니다.
- 메서드 레퍼런스는
::
기호를 사용하여 표현하며, 메서드 이름과 클래스 또는 객체를 가리킵니다.
예를 들어, 아래 코드는 리스트의 모든 요소를 forEach()
로 출력합니다.
List<String> list = new ArrayList<>();
list.add("AAA");
list.add("BBB");
list.forEach((item) -> System.out.println(item));
위의 예제는 메소드 참조를 사용하는 아래 예제와 동일하게 동작합니다.
- 람다식
(item) -> System.out.println(item)
는 메소드 참조 방식System::out::println
로 간결하게 사용할 수 있음, 동작은 동일 - 함수에 전달되는 인자는 정해져있기 때문에, 굳이 입력하지 않아도 컴파일러는 알 수 있음. 이럴 때 메소드 참조를 사용하여 간단히 구현 가능.
- 메소드 참조에서는
::
기호를 사용하며, 람다식과 비교할 때 인자와->
기호 등이 생략되어있습니다.
List<String> list = new ArrayList<>();
list.add("AAA");
list.add("BBB");
list.forEach(System.out::println);
Java에는 다음과 같이 3종류의 메소드 참조가 있습니다. 아래에서 자세히 알아보겠습니다.
- 정적 메소드 레퍼런스(Static Method References)
- 인스턴스 메소드 레퍼런스(Instance Method References)
- 클래스 생성자 레퍼런스(Constructor References)
2. 정적 메소드 참조(Static Method References)
정적 메소드를 메소드 참조로 사용하는 것을 말합니다.
아래 예제에서 람다식 s -> Integer.parseInt(s)
는 메소드 참조 방식으로 Integer::parseInt
처럼 사용할 수 있으며, 동작은 동일합니다.
// 람다 표현식
Function<String, Integer> parseIntFunction = s -> Integer.parseInt(s);
// 메서드 레퍼런스
Function<String, Integer> parseIntFunction = Integer::parseInt;
예제
- 예제에서
Integer::parseInt
는 람다식s -> Integer.parseInt(s)
로 바꿔 쓸 수 있음
import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;
public class Example {
public static void main(String[] args) {
List<String> stringNumbers = new ArrayList<>();
stringNumbers.add("123");
stringNumbers.add("456");
// 메소드 레퍼런스를 사용하여 문자열을 정수로 변환
Function<String, Integer> parseIntFunction = Integer::parseInt;
// Function<String, Integer> parseIntFunction = s -> Integer.parseInt(s);
List<Integer> intNumbers = new ArrayList<>();
for (String str : stringNumbers) {
intNumbers.add(parseIntFunction.apply(str));
}
// 파싱된 정수 출력
for (Integer num : intNumbers) {
System.out.println(num);
}
}
}
Output:
123
456
3. 인스턴스 메소드 레퍼런스(Instance Method References)
객체의 멤버 메소드를 메소드 레퍼런스로 사용하는 것을 말합니다.
아래 예제에서 람다식 (str, prefix) -> str.startsWith(prefix)
는 메소드 레퍼런스 String::startsWith
로 표현할 수 있습니다.
// 람다 표현식
BiFunction<String, String, Boolean> startsWithFunction = (str, prefix) -> str.startsWith(prefix);
// 메서드 레퍼런스
BiFunction<String, String, Boolean> startsWithFunction = String::startsWith;
예제
- 예제에서
String::startsWith
는 람다식(str, prefixStr) -> str.startsWith(prefixStr)
로 바꿔 쓸 수 있음
import java.util.ArrayList;
import java.util.List;
import java.util.function.BiFunction;
public class Example {
public static void main(String[] args) {
List<String> strings = new ArrayList<>();
strings.add("apple");
strings.add("banana");
strings.add("cherry");
String prefix = "app";
// 메서드 레퍼런스를 사용하여 문자열이 특정 접두사로 시작하는지 확인
BiFunction<String, String, Boolean> startsWithFunction = String::startsWith;
// BiFunction<String, String, Boolean> startsWithFunction = (str, prefixStr) -> str.startsWith(prefixStr);
for (String str : strings) {
boolean startsWith = startsWithFunction.apply(str, prefix);
if (startsWith) {
System.out.println(str + " starts with " + prefix);
} else {
System.out.println(str + " does not start with " + prefix);
}
}
}
}
Output:
apple starts with app
banana does not start with app
cherry does not start with app
4. 클래스 생성자 레퍼런스(Constructor References)
클래스 생성자를 메소드 레퍼런스로 사용하는 경우를 말합니다.
아래 예제에서 람다식 () -> new ArrayList<>()
을 메소드 레퍼런스로 표현하면 ArrayList::new
가 됩니다.
// 람다 표현식
Supplier<List<String>> listSupplier = () -> new ArrayList<>();
// 메서드 레퍼런스
Supplier<List<String>> listSupplier = ArrayList::new;
예제
- 예제에서
ArrayList::new
는 람다식() -> new ArrayList<>()
로 바꿔 쓸 수 있음
import java.util.ArrayList;
import java.util.List;
import java.util.function.Supplier;
public class Example {
public static void main(String[] args) {
// 메서드 레퍼런스를 사용하여 ArrayList 인스턴스 생성
Supplier<List<String>> listSupplier = ArrayList::new;
//Supplier<List<String>> listSupplier = () -> new ArrayList<>();
// 새로운 ArrayList 인스턴스 생성
List<String> list = listSupplier.get();
// ArrayList에 요소 추가
list.add("Apple");
list.add("Banana");
list.add("Cherry");
// 요소 출력
for (String fruit : list) {
System.out.println(fruit);
}
}
}
Output:
Apple
Banana
Cherry