[사이드 프로젝트] 함수형 프로그래밍 익히기 With Java - Method Reference

gimseonjin616·2022년 5월 13일
0

Method Reference

자바는 오랜 기간 OOP 프로그래밍으로 개발되어 왔다. 따라서 기존 라이브러리들도 모두 Class(Object) 기반이다.

FP 방식으로 프로그래밍하면 기존의 Class 기반의 메소드를 사용할 수 없을까??

Java에서는 Method Reference를 사용해서 기본 메소드를 함수로 사용할 수 있도록 했다.

Method Reference는 크게 4 가지 방법이 있다.

1) 클래스의 static method를 사용할 때,

ClassName::staticMethodName

2) 선언된 객체의 instance method를 사용할 때,

objectName::instanceMethodName

3) 객체의 instance method를 사용할 때,

ClassName::instanceMethodName

4) 클래스의 constructor를 사용할 때,

ClassName::new

상황에 맞게 위 케이스에서 골라서 사용하면 된다.

클래스의 static method를 사용할 때

static method는 객체를 생성하지 않고 클래스명.메소드명으로 호출 가능한 메소드를 뜻한다.

인스턴스를 생성하지 않고 사용 가능하기 때문에 모든 인스턴스가 공통으로 사용하는, 같은 값으로 유지되어야 하는 경우 사용할 수 있다.

static method는 인스턴스가 필요없다. 즉 힙 메모리에 구현되지 않는다. 대신 Data 영역 내의 static 메모리에 저장된다.

따라서 instance method보다 빠르기 때문에 변경되는 인스턴스 값이 없는 경우에는 static method를 사용해보는 것도 고려해볼만 하다.

Static Method의 대표적인 예시로는 Integer의 ParseInt가 있다.

이 ParseInt를 파라미터로 넘기는 경우를 구현하면 아래와 같다.

public class main {
    public static void main(String[] args){
        Function<String, Integer> str2Int = Integer::parseInt;
        System.out.println(str2Int.apply("15"));
    }
}

선언된 객체의 instance method를 사용할 때

선언된 객체의 instance method를 사용하는 방법은 아래와 같다.

우선 사용할 타입의 객체를 선언해주고 그 객체의 메소드를 가져오면 된다.

public class main {
    public static void main(String[] args){
        String str = "hello";
        Predicate<String> str2Int2 = str::equals;
        System.out.println(str2Int2.test("hello"));
    }
}

객체의 instance method를 사용할 때

선언된 객체의 instance method를 사용할 때와 객체의 instance method를 쓸 때가 달라서 조심해야 한다.

위에서 두 String 값을 비교한 것을 객체 instance method를 사용한 방법으로 바꾸면 아래와 같다.

public class main {
    public static void main(String[] args){
        BiFunction<String, String, Boolean> str2Int3 = String::equals;
        System.out.println(str2Int3.apply("hello", "world"));

    }
}

여기서 중요한 점은 객체 인스턴스를 선언해서 메소드를 가져온 것이 아니기 때문에 파라미터로 객체 인스턴스를 구현해서 넘겨줘야 한다.

위 2) 선언한 객체의 instance method를 사용한 경우와 비교해보면 더 잘 알 수 있다.

public class main {
    public static void main(String[] args){
        String str = "hello";
        Predicate<String> str2Int2 = str::equals;
        System.out.println(str2Int2.test("hello"));

        BiFunction<String, String, Boolean> str2Int3 = String::equals;
        System.out.println(str2Int3.apply("hello", "world"));

    }
}

2)번의 경우, 비교할 값인 "hello"를 String 객체의 담아서 그 객체의 equals를 가져왔다.

따라서 이미 hello라는 비교 인스턴스를 정해놨기 때문에 파라미터로 비교 값 "hello"만 넣으면 된다.

그러나 3)번의 경우, "hello"를 객체로 선언하지 않고 String에서 바로 가져왔기 때문에 비교 대상과 비교 값 둘 다 필요하다.

따라서 두 값 모두 파라미터로 넣어줘야하며 BiFunction을 사용해야 한다.

클래스의 constructor를 사용할 때,

클래스의 생성자도 파라미터로 넘길 수 있다.

Car라는 클래스를 만들어서 테스트 해보면 아래와 같다.

public class main {
    public static void main(String[] args){
        BiFunction<String, String, Car> createCar = Car::new;
        System.out.println(createCar.apply("SUV", "Sonata"));
    }
}

profile
to be data engineer

0개의 댓글