메소드 레퍼런스(Method Reference)란
메소드 레퍼런스란, 람다식에서의 클래스의 메소드 호출을 간단하게 표현을 하는 방법이다. 람다 표현식이 메소드 호출 1회로 끝나는 경우, 메소드 레퍼런스를 이용하여 코드를 더욱 간결하게 작성할 수 있는 것이다.
예시로 아래의 코드를 보면,
@FunctionalInterface
public interface class Test {
void print(T t);
}
public class Main {
public static void main(String[] args) {
//메소드 레퍼런스 X
Test<String> t1 = (str) -> System.out.println(str);
t1.print("hello");
//메소드 레퍼런스 O
Test<String> t2 = System::println;
t2.print("hello");
}
}
t1 람다식이 System의 println 메소드를 1회 호출로 끝나기 때문에 t2와 같이 메소드 래퍼런스를 사용하여 간략하게 표현할 수 있다. 두 가지 표현식 모두 같은 의미를 가지고 있다.
위의 예시에서 보았듯이 메소드 래퍼런스는 [클래스명]::[메소드명]으로 표현하고, 상당 부분 생략된 간결한 표현이기 때문에 메소드의 인자와 리턴 타입에 대해서 정확히 인지하고 있어야 한다.
메소드 레퍼런스는 패턴에 따라 아래와 같이 분류할 수 있다.
- static 메소드 레퍼런스
- 매개변수의 인스턴스 메소드 레퍼런스
- 생성자 메소드 레퍼런스
- 외부 인스턴스 메소드 레퍼런스
static 메소드 레퍼런스
static 메소드 레퍼런스는 static method를 메소드 레퍼런스로 사용하는 것을 말한다.
public class Main {
@FunctionalInteface
interface Exceutable {
void doSomething(String text);
}
public static class Printer {
static void printSomething(String text) {
System.out.println(text);
}
}
public static void main(String[] args) {
Executable e1 = Printer::printSomething; //(str) -> Printer.printSomethin(str);
e1.doSomething("hello");
}
}
Instance 메소드 레퍼런스
매개변수의 타입이 명확할 때, 해당 타입 클래스의 메소드를 메소드 레퍼런스로 사용하는 것이다.
public class Main {
public static class Car {
String carName;
public Car(String carName) {
this.carName = carName;
}
public void printCar() {
System.out.println(this.carName);
}
}
public static void main(String[] args) {
List<Car> carList = Arrays.asList(new Car("genesis"), new Car("avante"));
//forEach를 하였을 경우, 매개변수의 타입은 무조건 Car이다!!
//매개변수가 명확하므로, Car 클래스의 메소드를 메소드 레퍼런스로 사용가능
carList.stream().forEach(Car::printCar());
//결과
//genesis
//avante
}
}
생성자 메소드 레퍼런스
이름 그대로 생성자를 메소드 레퍼런스로 표현하는 것이다.
public class Main {
@FunctionalInteface
public interface CreateCar {
Car create(String carName);
}
public static class Car {
String carName;
public Car(String carName) {
this.carName = carName;
}
public void printCar() {
System.out.println(this.carName);
}
}
public static void main(String[] args) {
ArrayList<Car> carList = new ArrayList<>();
//생성자 메소드 레퍼런스
CreateCar cc = Car::new; // str -> new Car(str);
carList.add(cc.create("genesis"));
carList.add(cc.create("avante"));
carList.stream().forEach(Car::printCar); //인스턴스 메소드 레퍼런스
}
}
외부 인스턴스 메소드 레퍼런스
일반적인 인스턴스 메소드 레퍼런스는 해당 타입의 클래스 내에 있는 메소드를 메소드 레퍼런스로서 사용하였다. 이와 반대로 외부 인스턴스의 메소드 또한 람다표현식에서 메소드 레퍼런스로 표현할 수 있다.
람다 표현식에서 외부의 있는 인스턴스의 메소드를 참조하는 것을 람다 캡쳐링(또는 외부 캡쳐링)이라고 한다.
public class Main {
@FunctionalInteface
public interface Test {
boolean test(String str);
}
public static void main(String[] args) {
String s1 = "hello";
Test t1 = str -> s1.eauals(str); //외부 캡쳐링 : 람다 내부에서 외부 인스턴스 참조
Test t2 = s1::equals;
System.out.println(t1.test("hi"));
System.out.println(t2.test("hello"));
}
}
위의 예시에서, 람다 표현식에서 외부에 String 클래스의 객체인 s1의 equals 메소드를 참조하는 것을 확인 할 수 있다.
'Programming > Java' 카테고리의 다른 글
[자바/Java] 스트림 Stream - 생성 (0) | 2023.10.15 |
---|---|
[자바/Java] Optional 개념 및 사용법 (1) | 2023.10.15 |
[자바/Java] 함수형 인터페이스 (1) | 2023.10.14 |
[자바/Java] lambda 개념 및 사용법 (0) | 2023.10.14 |
[자바/Java] Inner 클래스 (0) | 2023.10.14 |