Java

[java 8] 함수형 인터페이스와 람다 표현식 소개

딸기케잌🍓 2021. 9. 6. 00:09

함수형 인터페이스

추상 메소드를 하나만 가지고 있는 인터페이스입니다.

함수형 인터페이스를 정의하기 위해 @FunctionalInterface 애노테이션을 사용할 수 있습니다.

이 애노테이션은 자바에서 제공해줍니다.

 

java 8부터 인터페이스이지만 메서드안에 구현체가 있을 수 있고 default 메서드를 추가할 수도 있게 변경됐습니다.

 

<예제1> - 함수형 인터페이스

public interface RunSomething {
    void doIt();

//구현부가 있는 메서드
    static void printName(){
        System.out.println("dayeon");
    }

 //디폴트 메서드
    default void printAge(){
        System.out.println("20");
    }
}

RunSomething 인터페이스는 doIt이라는 추상 메소드를 하나만 가지고 있습니다.

pringName과 printAge 디폴트 메소드가 있지만 추상 메소드는 하나이므로 함수형 인터페이스라고 할 수 있습니다.

 

 

@FunctionalInterface 애노테이션을 이용하여 함수형 인터페이스라는 것을 명시하고 있습니다.

현재 추상 메소드가 2개이므로 'Multiple non-overriding abstract methods found in interface RunSomething'

에러가 납니다.

 

<예제2> - @FunctionalInterface 사용

@FunctionalInterface
public interface RunSomething {
    void doIt();
    void doIt2(); // 추상메서드가 2개인 상태

    static void printName(){
        System.out.println("dayeon");
    }

    default void printAge(){
        System.out.println("20");
    }
}

 

 

 

람다 표현식

람다를 자바에서는 특수한 형태의 오브젝트로 보고 있습니다. 이러한 오브젝트를 메소드 매개변수, 리턴 타입, 변수로 만들어서 사용할 수 있습니다.

함수형 인터페이스의 인스턴스를 만드는 방법으로 람다 표현식이 쓰일 수 있습니다.

 

아래 예제는 Runsomething클래스의 doIt 메소드를 오버라이딩 하고 있는 익명 내부 클래스입니다.

<예제3> - 람다 표현식을 사용하지 않은 익명 내부 클래스

public class Foo {
    public static void main(String[] args) {
        //익명 내부 클래스 anonymous inner class
        RunSomething runSomething = new RunSomething() {
            @Override
            public void doIt() {
                System.out.println("Hello");
            }
        };
    }
}

 

 

자바8 부터는 람다 표현식을 이용하여 간결하게 표현할 수 있게 해줍니다.

<예제4> - 람다 표현식을 사용하여 표현

public class Foo {
    public static void main(String[] args) {
        RunSomething runSomething = () -> System.out.println("Hello");
    }
}
public class Foo {
    public static void main(String[] args) {
        RunSomething runSomething = () -> System.out.println("Hello");
        runSomething.doIt();
    }
}

runSomething.doIt()으로 메소드를 실행할 수 있습니다.

 

<예제5> - 람다 표현식 예

메소드가 두 줄 이상일 때는 {} 를 사용합니다.

public class Foo {
    public static void main(String[] args) {
        RunSomething runSomething = new RunSomething() {
            @Override
            public void doIt() {
                System.out.println("Hello");
                System.out.println("람다 두 줄일 때");
            }
        };
    }
}
public class Foo {
    public static void main(String[] args) {
        RunSomething runSomething = () -> {
            System.out.println("Hello");
            System.out.println("람다 두 줄일 때");
        };
    }
}

 

 

자바에서 함수형 프로그래밍

first class object

first class object란?
  • 파라미터로 전달할 수 있다.
  • 반환값으로 사용할 수 있다.
  • 변수나 데이터 구조 안에 담을 수 있다.

자바는 보통 Object(객체)가 위 기능들을 수행했지만 자바8 부터는 함수형 프로그래밍을 지원하므로 메소드를 first-class-object로 사용할 수 있게 되었습니다.

 

순수함수 (Pure Function)

외부의 상태를 변경하거나 함수로 들어온 인자의 상태를 직접 변경하지 않고,

어떤 함수에 동일한 인자를 주었을 때 항상 같은 값을 리턴하는 함수입니다.

--> 외부의 값을 참조하거나 변경하지 않는 함수

 

 

<예제6> - 순수함수

@FunctionalInterface
public interface RunSomething {
    int doIt(int number);
}


public class Foo {
    public static void main(String[] args) {
        RunSomething runSomething = (number) -> number + 10;
    }
}

예제3의 경우 동일한 number 인자에 대해서 항상 같은 값을 리턴한다고 기대할 수 있으며 외부의 상태를 변경하는 것이 없어 순수함수라고 할 수 있습니다.

 

 

<예제7> - 순수함수가 아닌 경우

public class Foo {
	int baseNumber = 10;
    public static void main(String[] args) {
    	int baseNumber2 = 20;
        RunSomething runSomething = (number) -> number + baseNumber + baseNumber2;
    }
}

baseNumber, baseNumber2와 같은 함수 밖의 값을 참조해서 쓰는 경우 상태값을 가지고 있다 또는 상태값에 의존한다고 하며 순수함수라고 할 수 없습니다.

 

<예제8> - 순수함수가 아닌 경우2

public class Foo {
    public static void main(String[] args) {
        RunSomething runSomething = new RunSomething() {
            int num = 30;
            @Override
            public int doIt(int number) {
                num++;
                return 0;
            }
        };
    }
}

doIt 메서드 밖에서 선언한 num 변수의 값을 메서드에서 변경하고 있습니다. 외부 값을 변경하고 있으므로 순수 함수라고 볼 수 없습니다.

 

'Java' 카테고리의 다른 글

java length  (0) 2021.08.20
[Java] 컴파일러 vs 인터프리터 vs JIT compiler  (0) 2021.05.31
[Java] JVM 구조와 원리  (0) 2021.05.23
[Java] Static 변수, static 메소드  (0) 2021.05.23
[Java] String, StringBuffer, StringBuilder  (0) 2021.04.22