티스토리 뷰

반응형

함수형 인터페이스

 

 함수형 인터페이스란, 인터페이스 중 한 개의 추상 메서드를 갖는 것을 말한다.

간단히 아래와 같은 형태의 인터페이스를 함수형 인터페이스라고 부를 수 있다.

 

@FunctionalInterface
interface ExampleInterface {
    abstract void exampleMethod();
}

 

 java.lang의 @FunctionalInterface 어노테이션을 붙여 해당 인터페이스가 함수형 인터페이스의 조건에 부합하는지 컴파일 시점에 확인할 수 있다.

 

 

Java8의 함수형 인터페이스

 

 Java8 이전까지는 인터페이스에 상수와 추상 메서드만을 선언 가능했으나, Java8부터 인터페이스에 디폴트(default) 메서드와 정적(static) 메서드 또한 추가가 가능해졌다. 따라서 아래와 같은 형태도 결과적으로는 추상 메서드가 하나이므로 함수형 인터페이스라 할 수 있다.

 

@FunctionalInterface
public interface ExampleInterface {

    public int variable = 10;
    
    public abstract void abstractMethod();
    
    default void defaultPrint() {
        System.out.println("abc");
    }
    
    static void staticPrint() {
    	System.out.println("def");
    }
}

 

참고로 인터페이스의 추상 메서드 접근제어자는 public으로 간주되며 default나 static이 아닌 메서드는 무조건 abstract로 간주된다.

인터페이스 멤버 또한 무조건 public으로 간주된다. 따라서 위의 코드는 아래와 같이 간결히 적을 수 있다.

 

@FunctionalInterface
public interface ExampleInterface {

    int variable = 10;
    
    void abstractMethod();
    
    default void defaultPrint() {
        System.out.println("abc");
    }
    
    static void staticPrint() {
    	System.out.println("def");
    }
}

 


함수형 인터페이스가 왜 필요한가?

 

 함수형 인터페이스의 정의는 매우 간단한데, 결국 특수한 형태의 인터페이스에 불과하다. 왜 굳이 이런 인터페이스를 달리 명명할까?

 

 특수한 형태의 인터페이스를 별도로 명명하게 된 이유는 Java8에서 함수형 프로그래밍이 등장하며 값을 파라미터화하여 메서드의 인수로 넣어주는 대신, 동작 자체를 파라미터화하여 인수로 넣어주는 과정에서 이런 함수형 인터페이스의 인스턴스를 사용하기 때문이다.

 

 함수형 인터페이스에는 추상 메서드가 오직 하나이므로 람다를 통해 구현체를 만들어도 타입 추론이 가능하지만 일반적인 인터페이스의 경우 추상 메서드가 여럿이므로 추상 메서드의 시그니처가 동일할 때 타입 추론이 불가능하다.

 

 

 예를 들어 만약 여러 추상메서드가 존재하는 인터페이스의 인스턴스를 람다로 만들 수 있었다면 아래와 같은 상황에서 문제가 발생했을 것이다.

 

public interface Runnable {
    
    void run1();
    
    void run2();
}

. . .

Runnable r = () -> System.out.println("Run");
// 람다는 run1과 run2중 어떤 것의 구현인가?

 

이러한 문제로 자바는 함수형 인터페이스를 인수로 받는 메서드에만 람다식을 사용할 수 있게 설계되었다.

 

 

왜 '함수형'이라는 이름을 가졌을까?

 

 자바의 함수형 프로그래밍의 핵심 요소 중 하나는 메서드나 람다를 일급값으로 사용할 수 있다는 것이다.

기존의 자바에선 메서드의 파라미터로 기본 자료형, 혹은 참조 자료형만을 넘겨줄 수 있었고 일련의 동작 자체를 넘겨주는 것은 불가능했다. 전달이 불가능했던 이급 값(혹은 이급 시민)이었던 동작들의 묶음을 전달이 가능한 일급 값으로 만드는 것이 Java8에서 가능해진 것이고, 동작의 묶음이 추상 메서드가 하나인 인터페이스를 통해 함수로 규정되므로 'Functional'이라는 이름을 가지게 된 것이다.

반응형