코드지우개

람다식 ⑤ 본문

java

람다식 ⑤

코드지우개 2023. 9. 5. 10:53
반응형

 

 
메소드 참조 (Method references)

메소드를 참조해서 매개변수의 정보 및 리턴 타입을 알아내서 람다식에서 불필요한 매개변수를 제거하는 것이 목적이다.람다식은 종종 기존 메소드를 단순하게 호출만 하는 경우가 있다.

(left, right) -> Math.max(left, right); 
Math::max; <----- 메소드 참조
 

매개변수가 2개가 주어지고 Math.max()를 호출할 때 2개의 매개변수를 넣어주었다.

실행 부를 보면 단순하게 메소만 호출하고 있다.

이 경우에 매 개값 2개가 메소드 호출할 때 사용하게 되는데 매개변수에도 left, right를 적고 메소드 호출할 때 또 left, right를 적게 돼서 불필요한 중복이 발생하기 때문에 이를 해결하게 위해 메소드 참조를 사용하면 된다.

 

메소드 참조도 람다식과 마찬가지로 인터페이스의 익명 구현 객체로 생성된다.

  • 타깃 타입에서 추상 메소드의 매개변수 및 리턴 타입에 따라 메소드 참조도 달라진다.
  • ex) IntBinayOperator 인터페이스는 두 개의 int 매 개값을 받아 int 값을 리턴하므로 동일한 매 개값과 리턴 타입을 갖는 Math 클래스의 max() 메소드를 참조할 수 있다.
IntBinaryOperator operator = Math::max;
 
 

정적 메소드와 인스턴스 메소드 참조

정적 메소드를 참조할 때와 인스턴스 메소드를 참조할 때 좀 다르게 사용된다.
정적 메소드를 참조할 때는 '클래스::메서드'로 작성하면 되고 인스턴스 메소드를 참조할 때는 '참조 변수::메서드'로 작성하면 된다.

public class Calculator{
    public static int staticMethod(int x, int y){
        return x + y;
    }

    public int instanceMethod(int x, int y){
        return x + y;
    }
}
 

Calculator라는 클래스에 정적 메소드와 인스턴스 메소드가 있을 때 메소드 참조를 하려면 아래 코드처럼 하면 된다.

IntBinaryOperator operator;

//정적 메소드 참조
operator = (x,y) -> Calculator.staticMethod(x,y);
System.out.println("결과1: " + operator.applyAsInt(1,2));
                    ↓
operator = Calculator::staticMethod;
System.out.println("결과2: " + operator.applyAsInt(3,4));

//인스턴스 메소드 참조
Calculator obj = new Calculator();
operator = (x,y) -> obj.instanceMethod(x,y);
System.out.println("결과3: " + operator.applyAsInt(5,6));
                    ↓
operator = obj::instanceMethod;
System.out.println("결과4: " + operator.applyAsInt(7,8));

//출력
결과1: 3
결과2: 7
결과3: 11
결과4: 15
 
 

매개변수의 메소드 참조
(a,b) -> {a.instanceMethod(b);}
 

위에 코드를 보면 2개의 매개변수를 받아서 실행부에서 첫 번째 매개변수 a에 instanceMethod 메소드를 호출을 해서 두 번째 매 개값인 b를 instanceMethod 메소드의 매 개값으로 사용했다.

이와 같은 람다식을 메소드 참조로 표현하자면 '클래스::instanceMethod'로 표현할 수 있다.

이때 '클래스'는 a의 타입이 된다. a의 타입이 String일 경우 클래스는 String이 된다.

public static void main(String[] args){
    ToIntBiFunction<String, String> function;
/*
    compareToIgnoreCase : a가 b보다 사전순으로 먼저 오면 음수 같으면 0 뒤에오면 양수 
    IgnoreCase는 대소문자를 가리지 않고 알파벳만으로 비교하겠다.
*/
    function = (a,b) -> a.compareToIgnoreCase(b); 
    print(function.applyAsInt("java8", "JAVA8")); // function.applyAsInt("java8", "JAVA8") 값 : 0
                    ↓
    function = String::compareToIgnoreCase;
    print(function.applyAsInt("java8", "JAVA8"))
}

public static void print(int order){
    if(order < 0) {System.out.println("사전순으로 먼저 옵니다.");}
    else if(order == 0) {System.out.println("동일한 문자열 입니다.");}
    else {System.out.println("사전순으로 나중에 옵니다.");}
}

//출력
동일한 문자열 입니다.
 
 

생성자 참조
(a,b) -> {return new 클래스(a,b);}
 

위에 코드를 보면 2개의 매개변수를 받아서 실행부에서 new 연산자를 사용해서 클래스에 객체를 생성하고 이때 매 개값으로 제공된 a, b를 생성자에 매 개값으로 제공하고 이렇게 생성된 객체를 리턴하고 있다.

 

이와 같이 실행부에 객체를 생성하고 리턴하는 코드만 있는 람다식을 생성자 참조로 표현하자면 '클래스::new'로 표현할 수 있다.

public Member(String id){
    System.out.println("Member(String id) 실행");
    this.id = id;
}

public Member(String name, String id){
    System.out.println("MEmber(String name, String id) 실행");
    this.name = name;
    this.id = id;
}
 

위에 코드처럼 Member 클래스에 id를 받는 생성자와 name, id를 받는 생성자가 있을 때 생성자 참조를 하려면 아래 코드처럼 하면 된다.

Function<String, Member> function1 = Member::new;
Member member = function1.apply("angel"); //Member(String id) 실행


BiFunction<String, String, Member> function2 = Member::new;
Member member2 = function2.apply("천사","angel"); //MEmber(String name, String id) 실행
 

 

 

반응형

'java' 카테고리의 다른 글

File을 MultipartFile 타입으로 변환  (0) 2023.09.05
RestTemplate.execute()를 사용하여 File타입으로 리턴 받기  (0) 2023.09.05
람다식 ④  (0) 2023.06.05
람다식 ③  (0) 2023.06.05
람다식 ②  (0) 2023.06.05
Comments