온라인 상의 자바 예시 코드를 보면 종종
Member::new 이런식으로 ::new 혹은 다른 메소드로 코드가 짜여진 경우가 있다
1. 메소드 레퍼런스
- 람다 표현식을 구현할 때 쓸 수 있는 방법으로
기존에 있던 다른 메소드를 참조하여 그 메소드 자체를 함수형 인터페이스의 구현체로 사용 - 람다의 구현 자리를 기존에 이미 있는 어떤 메서드를 참조하는 방식
- 람다 표현식이 단 하나의 메소드만을 호출하는 경우에 해당 람다 표현식에서
불 필요한 매개변수를 제거하고 사용할 수 있다. - :: 연산자를 이용해 메소드 이름과 클래스를 분리하거나, 메소드 이름과 객체의 이름을 분리한다.
- 클래스::메소드
- 객체::메소드
- 클래스::new
2. 유형
1) 스태틱 메소드 참조(Static Method Reference)
클래스::정적메소드 (static)
public class Calculator {
public static int add(int a, int b) {
return a + b;
}
}
import java.util.function.BiFunction;
public class Main {
public static void main(String[] args) {
// BiFunction을 사용하여 두 정수를 더하는 연산을 정의
BiFunction<Integer, Integer, Integer> addFunction = Calculator::add;
// 정적 메서드 참조를 사용하여 add 메서드를 호출
int result = addFunction.apply(3, 5);
System.out.println("결과: " + result);
}
}
BiFunction<T, U, R>
- Java에서 함수형 프로그래밍을 지원하는 함수형 인터페이스(Functional Interface)중 하나
- 함수형 인터페이스란 단 하나의 추상 메서드를 가지는 인터페이스로, 람다 표현식이나 메소드 참조와 같은
함수형 프로그래밍 기법을 사용하기 위해 활용된다. - 두 개의 입력 인수를 받아들이고, 결과를 받아들이고, 결과를 반환하는 함수 표현
@FunctionalInterface
public interface BiFunction<T, U, R> {
R apply(T t, U u);
}
- T 는 첫 번째 인수의 타입을 나타낸다
- U 는 두 번째 인수의 타입을 나타낸다
- R 은 결과 값의 타입을 나타낸다
2) 특정 객체의 인스턴스 메소드 참조(Instance Method Reference)
객체::인스턴스메소드 (public)
public class Person {
private String name;
public Person(String name) {
this.name = name;
}
public void sayHello() {
System.out.println("안녕하세요, 제 이름은 " + name + "입니다.");
}
}
import java.util.function.Consumer;
public class Main {
public static void main(String[] args) {
Person person = new Person("Alice");
// Consumer를 사용하여 sayHello 메서드를 참조
Consumer<Person> sayHelloConsumer = Person::sayHello;
// 인스턴스 메서드 참조를 사용하여 sayHello 메서드를 호출
sayHelloConsumer.accept(person);
}
}
Consumer<T>
- Java에서 함수형 프로그래밍을 지원하는 함수형 인터페이스(Functional Interface)중 하나
- 입력값을 받아서 어떤 작업을 수행하지만, 결과값은 반환하는 않은 경우에 사용
@FunctionalInterface
public interface Consumer<T> {
void accept(T t);
}
- T 는 입력값의 타입을 나타낸다
3) 생성자 참조(Constructor Method Reference)
클래스::new
public class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public void introduce() {
System.out.println("안녕하세요, 제 이름은 " + name + "이고, 나이는 " + age + "세 입니다.");
}
}
import java.util.function.Function;
public class Main {
public static void main(String[] args) {
// Function을 사용하여 생성자 메서드를 참조
Function<String, Person> personConstructor = Person::new;
// 생성자 메서드 참조를 사용하여 Person 객체를 생성
Person person = personConstructor.apply("Alice");
// 생성된 객체를 사용
person.introduce();
}
}
Function<T, R>
- Java에서 함수형 프로그래밍을 지원하는 함수형 인터페이스(Functional Interface)중 하나
- 하나의 입력을 받아서 결과를 반환하는 함수
@FunctionalInterface
public interface Function<T, R> {
R apply(T t);
}
- T 는 입력값의 타입을 나타낸다
- R 은 결과값의 타입을 나타낸다
2. 'Person::new ' vs 'new Person()' ?
참조 vs 직접 생성
위의 예시에서
Function<String, Person> personConstructor = Person::new
-> Person 클래스의 생성자를 참조하고, apply 메서드를 호출하면 Person 객체가 생성된다.
new Person사용시에는
Person person = new Person("Alice");
-> Person 객체를 직접 생성한다.
즉, 'Person::new'를 사용하면 필요한 시점에 'apply' 메서드를 호출하여 객체를 생성할 수 있고, 다른 매개변수를 받는 생성자를 참조하여 다양한 생성자를 호출할 수 있으며, 재상용이 가능하다.