Java의 메서드 참조 방식 4가지
- 정적 메서드 참조 : Static method reference
- 생성자 참조 : constructor reference
- 바운드 비정적 메서드 참조 : bound non-static method reference
- 언바운드 비정적 메서드 참조 : unbound non-static method reference
정적 메서드 참조
@Test
void staticMethodReference() {
Function<String, Integer> asLambda = s -> Integer.parseInt(s);
Function<String, Integer> asRef = Integer::parseInt;
Integer i = asLambda.apply("10");
Assertions.assertEquals(10, i);
i = asRef.apply("11");
Assertions.assertEquals(11, i);
}
생성자 참조
@Test
void constructorReference() {
Supplier<String> asLambda = () -> new String();
Supplier<String> asRef = String::new;
String s = asLambda.get();
s = "Hello";
Assertions.assertEquals("Hello", s);
String s2 = asRef.get();
s2 = "Hello2";
Assertions.assertEquals("Hello2", s2);
}
바운드 비정적(인스턴스) 메서드 참조
@Test
void boundNonStaticMethodReference() {
String str = "Hello";
Function<Integer, String> asLambda = i -> str.substring(i);
Function<Integer, String> asRef = str::substring;
String s = asLambda.apply(1);
Assertions.assertEquals("ello", s);
s = asRef.apply(2);
Assertions.assertEquals("llo", s);
}
언바운드 비정적(인스턴스) 메서드 참조
@Test
void unboundNonStaticMethodReference() {
BiFunction<String, Integer, String> asLambda = (s, i) -> s.substring(i);
BiFunction<String, Integer, String> asRef = String::substring;
String hello = "Hello";
String s = asLambda.apply(hello, 1);
Assertions.assertEquals("ello", s);
s = asRef.apply(hello,2);
Assertions.assertEquals("llo", s);
}
Java 공식 문서에서 메서드 참조(Method Reference)와 관련된 내용을 살펴보면, 메서드 참조는 함수형 인터페이스의 인스턴스를 생성할 때 메서드를 간단하게 참조할 수 있는 방법을 제공한다고 설명하고 있습니다. 특히, String::equals와 같은 형태의 메서드 참조는 인스턴스 메서드 참조로 분류됩니다.
이제 코드 예제를 통해 String::equals가 BiPredicate<String, String>으로 사용되는 방식을 설명해보겠습니다:
@Test
void FunctionalTest() {
BiPredicate<String, String> equalsFunction = String::equals;
String abc = "abc";
Assertions.assertTrue(equalsFunction.test(abc, "abc"));
}
메서드 참조 설명
- 메서드 참조 유형: String::equals는 인스턴스 메서드 참조(instance method reference)입니다. 이 유형의 참조는 특정 객체가 아닌, 임의의 객체에 대해 메서드를 호출할 때 사용됩니다. 문법은 ContainingType::methodName이며, 여기서 ContainingType은 메서드가 정의된 클래스입니다.
- BiPredicate 인터페이스: BiPredicate<T, U>는 함수형 인터페이스로, 두 개의 입력을 받아 boolean을 반환하는 test라는 메서드를 정의합니다.
- String::equals: String::equals 메서드 참조는 BiPredicate<String, String> 타입과 호환됩니다. 이는 BiPredicate<String, String>의 test 메서드가 String 타입의 두 매개변수를 받고, String 클래스의 equals 메서드도 마찬가지로 두 번째 인자로 String을 받기 때문입니다.
@FunctionalInterface
public interface BiPredicate<T, U> {
boolean test(T t, U u);
}
내부 동작 설명
BiPredicate<String, String> equalsFunction = String::equals;는 내부적으로 다음과 같은 람다 표현식으로 변환됩니다:
BiPredicate<String, String> equalsFunction = (str1, str2) -> str1.equals(str2);
따라서, equalsFunction.test(abc, "abc")는 abc.equals("abc")와 동일하게 동작합니다.
요약
- String::equals는 인스턴스 메서드 참조입니다.
- BiPredicate<String, String>는 두 개의 String을 받아 boolean을 반환하는 함수형 인터페이스입니다.
- String::equals를 BiPredicate<String, String>에 할당하면, 이는 두 개의 문자열을 비교하는 람다 표현식 (str1, str2) -> str1.equals(str2)와 동등합니다.
- 메서드 참조를 사용하면 코드가 간결하고 명확해집니다.
Java 공식 문서에서는 이러한 메서드 참조와 람다 표현식의 변환 과정, 그리고 함수형 인터페이스와의 호환성에 대해 자세히 설명하고 있습니다. 메서드 참조는 코드의 가독성을 높이고, 명확한 의도를 전달할 수 있는 강력한 도구입니다.
'프로그래밍 > OOP_Pattern_TDD' 카테고리의 다른 글
스트림 성능 개선 & 람다식 간소화 사례 (0) | 2024.06.27 |
---|---|
[한글화 프로젝트] TDD는 죽었는가? (0) | 2024.05.23 |
OOP KISS 원칙과 YANGI 원칙 (0) | 2024.05.02 |
OOP SOLID 원칙 간편 정리 (0) | 2024.04.30 |
기본부터 다시 이해하는 OOP (0) | 2024.04.23 |