Study/Java

자바 기본서를 다시 읽다. 6 - 메소드 참조

going.yoon 2022. 3. 29. 00:19

메소드 참조

메소드 참조란, 메소드를 참조하여 매개변수의 정보 및 리턴 타입을 알아내어 람다식에서 불필요한 매개변수를 제거하는 것이다.

예를들어 아래와 같은 코드가 있을 때, 람다식은 단순히 두개의 값을 Math.max() 메소드의 매개값으로 전달하는 역할만 한다.

( o1 , o2 ) -> Math.max(o1, o2);

 

이는 메소드 참조를 통해 아래와 같이 간결하게 변환할 수 있다.

IntBinaryOperator operator = Math :: max;

 

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

정적메소드와 인스턴스 메소드를 참조하는 방식은 다음과 같다.

  • 정적 메소드 - 클래스::메소드
  • 인스턴스 메소드 - 참조변수::메소드
import java.util.function.IntBinaryOperator;

public class Calculator {

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

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



public class MethodReferencesExample {
    public static void main (String[] args){
        IntBinaryOperator operator;

        // # 1. static method 참조
        operator = (x, y) -> Calculator.staticMethod(x, y);
        System.out.println("static method 참조 result : " + operator.applyAsInt(1, 2));

        // 1.1 static method를 메소드 참조를 통해 참조
        operator = Calculator::staticMethod;
        System.out.println("method 참조를 통한 static method 참조 result : " + operator.applyAsInt(3, 4));

        // #2. instance method 참조
        Calculator obj = new Calculator();
        operator = (x, y) -> obj.instanceMethod(x,y);
        System.out.println("instancd method 참조 result : " + operator.applyAsInt(5, 6));

        // #2.1
        operator = obj::instanceMethod;
        System.out.println("method 참조를 통한 instance method 참조 result : " + operator.applyAsInt(7, 8));

    }
}

 

매개변수의 메소드 참조

클래스의 정적 메소드는 클래스::staticMethod로, 인스턴스의 메소드는 인스턴스명::instanceMethod로 참조한다고 하였지만,

클래스::instanceMethod를 사용함으로써 람다식의 외부 클래스 멤버인 메소드를 호출하는 것이 아닌, 람다식에서 제공되는 매개변수의 메소드를 호출 할 수 있다. 

 

import java.util.function.ToIntBiFunction;

public class ArgumentMethodReferenceExample {
    public static void main ( String[] args ){
        ToIntBiFunction<String, String> function ;

        function = (a, b) -> a.compareToIgnoreCase(b);
        print(function.applyAsInt("Java8" , "JAVA8"));

        // String의 인스턴스 메소드인 compareToIgnoreCase를 호출
        // 이때 사용된 함수적 인터페이스는 String 2개를 매개값으로 받고 int를 리턴하는 ToIntBiFunction이다.
        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 Clazz(a,b);}

//아래와 같이 대체 가능
Clazz::new

 

아래의 코드를 통해 생성자는 Function API에서 넘겨주는 인자 수에 따라서 호출됨을 확인할 수 있다.

import java.util.function.BiFunction;
import java.util.function.Function;

// #1. Member Class
public class Member {
    private String name;
    private String id;

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

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

    public String getName() { return this.name ;}
    public String getId() { return this.id;}
}



// #2. Member의 생성자 참조
public class ConstructorReferencesExample {
    public static void main ( String [] args) {
    
    	// # 3. String을 Member 형으로 변환하는 Function에서 Member의 매개 1개를 가지는 생성자 호출
        Function<String, Member> function = Member::new;
        Member member = function.apply("angel");
		
        // #4. BiFunction API에서 매개 2개를 가지는 생성자 호출
        BiFunction<String, String, Member> function2 = Member::new;
        Member member2 = function2.apply("신천사" , "angel2");
    }
}