자바 - 메서드 참조

안녕하세요, 자바 프로그래머를 꿈꾸는 여러분! 오늘은 처음에는 조금 두려울 수 있는 주제이지만, 익숙해지면 정말 유용하다는 주제에 대해 깊이 들어가 볼 거예요. 우리는 자바의 메서드 참조에 대해 이야기할 거예요. 그럼, 좋아하는 음료를 준비하고 편하게 앉아서 함께 이 흥미로운 여정에 떠나보죠!

Java - Method References

메서드 참조란 무엇인가요?

자세히 들어가기 전에 간단한 질문부터 해볼까요? 정확히 메서드 참조는 무엇인가요? 글쎄요, 쿠키를 잘 만드는 친구가 있다고 상상해봅시다. 매번 쿠키를 원할 때 루트를 전부 설명할 필요는 없죠. "쿠키를 만드는 거 하렴" 이렇게 말하면 돼요. 이것이 바로 자바에서의 메서드 참조란 거예요 – 메서드를 실행하지 않고 참조하는 간단한 방법이죠.

메서드 참조는 자바 8에서 람다 표현식 기능 일부로 도입되었습니다. 메서드나 생성자를 호출하지 않고 참조할 수 있는 방법을 제공합니다. "필요할 때 사용하렴" 이렇게 가리키는 것과 같아요.

자바 메서드 참조의 유형

이제 기본적인 이해를 가지셨으니, 다양한 유형의 메서드 참조를 탐험해봅시다. 네 가지 주요 유형이 있습니다:

  1. 정적 메서드 참조
  2. 특정 객체의 인스턴스 메서드 참조
  3. 특정 타입의 임의의 객체의 인스턴스 메서드 참조
  4. 생성자 참조

이제 각각을 자세히 살펴보고 코드 예제를 살펴보겠습니다.

1. 정적 메서드 참조

이것은 아마 가장 쉽게 이해할 수 있는 유형일 것입니다. 클래스의 정적 메서드를 참조하는 경우입니다. 예제를 보겠습니다:

import java.util.Arrays;
import java.util.List;

public class StaticMethodReference {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);

// 람다 표현식 사용
numbers.forEach(number -> System.out.println(number));

// 메서드 참조 사용
numbers.forEach(System.out::println);
}
}

이 예제에서 System.out::printlnSystem.out 객체의 정적 println 메서드에 대한 메서드 참조입니다. 이는 number -> System.out.println(number) 람다 표현식과 동등하지만, 더 간결하고 가독성이 좋습니다.

2. 특정 객체의 인스턴스 메서드 참조

이 유형의 메서드 참조는 기존 객체의 인스턴스 메서드를 참조할 때 사용됩니다. 예제를 보겠습니다:

public class InstanceMethodReference {
public void printUpperCase(String s) {
System.out.println(s.toUpperCase());
}

public static void main(String[] args) {
InstanceMethodReference imr = new InstanceMethodReference();
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");

// 람다 표현식 사용
names.forEach(name -> imr.printUpperCase(name));

// 메서드 참조 사용
names.forEach(imr::printUpperCase);
}
}

여기서 imr::printUpperCaseimr 객체의 printUpperCase 메서드에 대한 메서드 참조입니다. 이는 name -> imr.printUpperCase(name) 람다 표현식과 동등합니다.

3. 특정 타입의 임의의 객체의 인스턴스 메서드 참조

이 유형은 좀 더 복잡하지만, 따라오세요! 이 유형의 메서드 참조는 특정 타입의 임의의 객체의 메서드를 호출할 때 사용됩니다. 예제를 보겠습니다:

import java.util.Arrays;
import java.util.List;

public class ArbitraryObjectMethodReference {
public static void main(String[] args) {
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");

// 람다 표현식 사용
names.sort((s1, s2) -> s1.compareToIgnoreCase(s2));

// 메서드 참조 사용
names.sort(String::compareToIgnoreCase);
}
}

이 예제에서 String::compareToIgnoreCaseString 클래스의 compareToIgnoreCase 메서드에 대한 메서드 참조입니다. 이는 (s1, s2) -> s1.compareToIgnoreCase(s2) 람다 표현식과 동등합니다.

4. 생성자 참조

마지막으로, 생성자에 대한 메서드 참조를 사용할 수도 있습니다. 이렇게 작동합니다:

import java.util.function.Supplier;

class Person {
private String name;

public Person() {
this.name = "Unknown";
}

public String getName() {
return name;
}
}

public class ConstructorMethodReference {
public static void main(String[] args) {
// 람다 표현식 사용
Supplier<Person> personSupplier1 = () -> new Person();

// 생성자 참조 사용
Supplier<Person> personSupplier2 = Person::new;

Person person1 = personSupplier1.get();
Person person2 = personSupplier2.get();

System.out.println(person1.getName());  // 출력: Unknown
System.out.println(person2.getName());  // 출력: Unknown
}
}

이 예제에서 Person::newPerson 클래스의 생성자에 대한 메서드 참조입니다. 이는 () -> new Person() 람다 표현식과 동등합니다.

메서드 참조를 사용하는 이유는 무엇인가요?

이제 "람다 표현식을 사용할 수 있을 테니 메서드 참조를 왜 사용해야 하지?"라고 궁금해할 수 있습니다. 좋은 질문입니다! 여기 몇 가지 이유가 있습니다:

  1. 가독성: 메서드 참조는 코드의 가독성과 간결성을 높입니다.
  2. 재사용성: 기존의 메서드 구현을 재사용할 수 있습니다.
  3. 성능: 일부 경우 메서드 참조가 람다 표현식보다 약간 더 효율적일 수 있습니다.

결론

그렇게 저희는 자바의 메서드 참조에 대한 기본을 다루었습니다. 기억해두세요, 새로운 개념을 배우는 것처럼, 메서드 참조에 익숙해지기 위해서는 연습이 필요합니다. 하지만 익숙해지면, 코드가 더 깔끔하고 표현력이 강화될 것입니다.

마무리하며, 제 가르침 경험에서的一则 이야기를 공유하고 싶습니다. 한 번은 메서드 참조에 어려움을 겪는 학생이 있었습니다. 그는 계속해서 "손가락 없이 뭘 가리키려고 하는 것 같아!"라고 말했어요. 하지만 연습을 좀 했더니 "이제 알겠다! TV를 매번 걸어가지 않고 리모컨을 사용하는 것 같아!"라고 외치며 깨달았어요. 바로 그런 거예요 – 메서드 참조는 메서드에 대한 작은 리모컨 같아요.

그럼, 계속 코딩하고 연습하며, 가장 중요한 것은 자바를 즐기세요! 기억해두세요, 모든 마스터는 처음엔初心자였습니다. 코딩하는 기쁨을 누리세요!

Credits: Image by storyset