메서드 참조(Method reference)란?
Java 8에 도입된 메서드 참조는 class::methodName 구문을 사용하여 클래스 또는 객체에서 메서드를 참조할 수 있습니다.
람다식(Lambda Expression)의 가장 큰 장점 중 하나는 코드가 짧아진다는 것인데, 람다식에 메서드 참조를 사용하면 코드를 더 간결하고 가독성 있게 만들 수 있습니다.
// 람다식
str -> str.toString()
// 메서드 참조
String::toString
// 람다식
str -> str.length()
// 메서드 참조
String::length
// 람다식
(int x, int y) -> x.compareTo(y)
// 메서드 참조
Integer::compareTo
메서드 참조는 이중 콜론(::)을 사용하여 클래스 이름과 메서드 이름을 구분하며, 람다식과 달리 인수를 전달할 필요가 없습니다. 인수는 메서드 참조 타입에 따라 처리됩니다.
메서드 참조 유형
- 정적 메서드에 대한 메서드 참조(Class::StaticMethodName)
- Object 인스턴스 메서드에 대한 참조(Object::instanceMethodName)
- 특정 타입(또는 클래스)에 대한 인스턴스 메서드에 대한 메서드 참조(Class::instanceMethodName)
- 생성자에 대한 메서드 참조(Class::new)
Java 8은 네 가지 유형의 메서드 참조를 제공합니다.
정적 메서드 참조
아래와 같은 함수형 인터페이스가 존재합니다.
@FunctionalInterface
public interface IAdd {
int add(int x, int y);
}
그리고 두 개의 매개변수 합산을 반환하는 MathUtils 클래스가 있습니다.
public class MathUtils {
public static int AddElement(int x, int y) {
return x + y;
}
}
다음 예제는 람다식을 사용하는 방법과 메서드 참조를 사용하는 방법을 보여줍니다.
public class Main {
public static void main(String args[]) {
System.out.println("Lambda Expression");
IAdd addLambda = (x, y) -> MathUtils.AddElement(x, y);
System.out.println(addLambda.add(10, 20));
System.out.println("Method Reference");
IAdd addMethodRef = MathUtils::AddElement;
System.out.println(addMethodRef.add(20, 40));
}
}
실행 결과
Lambda Expression
30
Method Reference
60
Object 인스턴스 메서드 참조
MathUtils 클래스의 AddElement() 메서드를 비정적(non-static) 메서드로 변경합니다.
public class MathUtils {
public int AddElement(int x, int y) {
return x + y;
}
}
다음 예제는 객체를 생성하고 객체의 메서드를 호출하는 방법을 보여줍니다.
public class Main {
public static void main(String args[]) {
// MathUtils 클래스의 객체를 생성합니다.
MathUtils mu = new MathUtils();
// 객체로 메서드를 호출하는 람다식입니다.
System.out.println("Lambda Expression");
IAdd addLambda = (x, y) -> mu.AddElement(x, y);
System.out.println(addLambda.add(10, 20));
// 객체로 메서드를 호출하는 메서드 참조입니다.
System.out.println("Method Reference");
IAdd addMethodRef = mu::AddElement;
System.out.println(addMethodRef.add(20, 40));
}
}
실행 결과
Lambda Expression
30
Method Reference
60
위 예제는 다음 예제처럼 객체를 생성하지 않고 람다식 또는 메서드 참조에서 MathUtils 클래스를 인스턴스화 할 수 있습니다.
public class Main {
public static void main(String args[]) {
// 클래스를 인스턴스화하여 메서드를 호출하는 람다식입니다.
System.out.println("Lambda Expression");
IAdd addLambda = (x, y) -> new MathUtils().AddElement(x, y);
System.out.println(addLambda.add(10, 20));
// 클래스를 인스턴스화하여 메서드를 호출하는 메서드 참조입니다.
System.out.println("Method Reference");
IAdd addMethodRef = new MathUtils()::AddElement;
System.out.println(addMethodRef.add(20, 40));
}
}
특정 타입(클래스)에 대한 인스턴스 메서드에 대한 메서드 참조
Arrays.sort() 메서드의 첫 번째 매개변수는 컬렉션 배열이며, 두 번째 매개변수는 Comparator 객체입니다. 오름차순으로 정렬하며 대소문자를 구분합니다.
String[] strArr = {"a", "B", "e", "c", "D"};
Arrays.sort(strArr);
System.out.println("Sorted strArr[] : " + Arrays.toString(strArr));
실행 결과
Sorted strArr[] : [B, D, a, c, e]
대소문자 구분 없이 정렬하고 싶은 경우 두 번째 매개변수인 Comparator 객체를 다음과 같이 구현합니다.
String[] strArr = {"a", "B", "e", "c", "D"};
Arrays.sort(strArr, new Comparator<String>() {
@Override
public int compare(String s1, String s2) {
return s1.compareToIgnoreCase(s2);
}
});
System.out.println("Sorted strArr[] : " + Arrays.toString(strArr));
실행 결과
Sorted strArr[] : [a, B, c, D, e]
두 번째 매개변수인 Comparator 객체는 함수형 인터페이스를 구현한 클래스와 유사합니다. 그러므로 람다식으로 변경할 수 있습니다.
Arrays.sort(strArr, (s1, s2) -> s1.compareToIgnoreCase(s2));
람다식은 메서드 참조로 변경할 수 있습니다.
Arrays.sort(strArr, String::compareToIgnoreCase);
생성자 참조
Stream의 collect() 메서드는 Supplier 인수를 허용합니다. Supplier는 매개변수가 없으며, void가 아닌 타입을 반환합니다. Supplier은 새로운 인스턴스를 반환하므로 람다식으로 호출할 수 있습니다.
List<Integer> intList = Arrays.asList(1, 2, 3, 4, 5);
String strConcat = intList.parallelStream().collect(
() -> new StringBuilder(),
(x, y) -> x.append(y),
(a, b) -> a.append(b)).toString();
System.out.println(strConcat);
실행 결과
12345
() -> new StringBuilder()를 생성자 메서드 참조로 변경할 수 있으며, 두 개의 람다식도 메서드 참조로 변경할 수 있습니다.
String concat1 = intList.parallelStream().collect(
StringBuilder::new,
StringBuilder::append,
StringBuilder::append).toString();
정리
- Java 8에 도입된 메서드 참조는 람다식을 더 간결하게 해주는 문법입니다.
- 메서드 참조는 모든 메서드에서 사용할 수 없으며, 정적 메서드 참조, Object 인스턴스 메서드 참조, 특정 타입(클래스)에 대한 인스턴스 메서드에 대한 메서드 참조, 생성자 참조에서 사용할 수 있습니다.
'Java' 카테고리의 다른 글
[Java]중첩 클래스 및 내부 클래스(Nested Class and Inner Class) (0) | 2022.06.21 |
---|---|
[Java]기본 메서드 또는 디폴트 메서드(Default Method) (0) | 2022.05.12 |
[Java]람다식, 람다표현식(Lambda expression) (0) | 2022.05.10 |
[Java]리플렉션(Reflection) (0) | 2022.05.08 |
[Java]반복자(Iterator) (0) | 2022.05.02 |
댓글