[Java]람다식 && 함수형 인터페이스

RyECODING·2022년 11월 22일

Java 심화

목록 보기
2/3

람다식

  • Java 8 버전에서 추가됨.

  • 함수형 프로그래밍 기법을 지원하는 자바의 문법요소.

  • 메서드를 하나의 ‘식(expression)’으로 표현.

  • 좀 더 간단하고 편리하게 표현하기 위해 고안된 요소.

현재 사용되고 있는 람다의 근간은 수학과 기초 컴퓨터과학 분야에서의 람다 대수이다. 간단히 말하자면 람다 대수는 수학에서 사용하는 함수를 보다 단순하게 표현하는 방법이다.

🟡 등장 이유

  • 람다식이 등장하게 된 이유는 불필요한 코드를 줄이고, 가독성을 높이기 위함.
    때문에 함수형 인터페이스의 인스턴스를 생성하여 함수를 변수처럼 선언하는 람다식에서는 메소드의 이름이 불필요하다고 여겨져서 이를 사용하지 않는다.
  • 대신 컴파일러가 문맥을 살펴 타입을 추론한다.
  • 또한 람다식으로 선언된 함수는 1급 객체이기 때문에 Stream API의 매개변수로 전달이 가능해진다.

🟡 표현 방식

//기존 메서드 표현 방식

반환타입 메소드명 (매개변수, ...) {
	실행문
}

//ex)
void sayhello() {
	System.out.println("Hello World!")
}

//람다식

(매개변수, ... ) -> { 실행문 ... }

//ex)
() -> System.out.println("Hello World!")

🟡 람다식의 형태

  • 람다식 기본 형태 : (매개변수) -> { 함수몸체; }
  • 매개변수 : 메소드 매개변수
  • "->" : 에로우, 코드블럭을 실행(호출)
  • "{ }" : 메소드 구현부
  • 인터페이스 객체변수명 = (매개변수) -> { 메소드 구현부 }

🟡 사용법

  • 기본적으로 반환타입과 이름을 생략
    : 때문에 이름이 없는 함수, 즉 익명 함수(anonymous function)라 부르기도 한다.

    익명함수
    	함수의 이름이 없는 함수로, 익명함수들은 모두 일급 객체.
    	1급 객체인 함수는 변수처럼 사용가능하며 매개 변수로 전달이 가능하는 등의 특징을 가짐.
    
    1급객체
    : 다음의 것들이 가능한 객체
    	1. 변수나 데이터 구조 안에 담을 수 있다.
    	2. 파라미터로 전달 할 수 있다.
    	3. 반환값으로 사용할 수 있다.
    	4. 할당에 사용된 이름과 무관하게 고유한 구별이 가능하다.
  • 반환값이 있는 메서드의 경우에는 return문과 문장 뒤에 오는 세미콜론(;)을 생략할 수 있다.

  • 함수몸체가 return문으로만 구성되어 있는 경우 괄호({})를 생략할 수 없다.

  • 특정 조건이 충족되면 람다식을 더욱 축약하여 표현 가능하다.
    1) 메서드 바디에 문장이 실행문 하나만 존재할 때 중괄호 생략 가능.
    2) 매개변수 타입을 쉽게 유추할 수 있는 경우에는 매개변수의 타입을 생략 가능.
    많은 경우 유추가 쉽기 때문에 대부분 생략 가능하다.

🟡 특징

  • 람다식 내에서 사용되는 지역변수는 final이 붙지 않아도 상수로 간주된다.
  • 람다식으로 선언된 변수명은 다른 변수명과 중복될 수 없다.

🟡 장점

  • 코드를 간결하게 만들 수 있다.
    : 불필요한 반복문의 삭제가 가능하며 복잡한 식을 단순하게 표현할 수 있다.

  • 식에 개발자의 의도가 명확히 드러나 가독성이 높아진다.
    : 코드에 드러내고자하는 개발자의 의도를 응축적으로 추상화시켜 나타낼 수 있어 가독성이 향상된다.

  • 함수를 만드는 과정없이 한번에 처리할 수 있어 생산성이 높아진다.

  • 병렬프로그래밍이 용이하다.
    : 멀티쓰레드를 활용하여 병렬처리를 사용할 수 있다.

  • 지연연산 수행
    : 지연연산을 수행 함으로써 불필요한 연산을 최소화 할 수 있다.

🟡 단점

  • 람다를 사용하면서 만든 무명함수는 재사용이 불가능하다.

  • 디버깅이 어렵다.

  • 람다를 남발하면 비슷한 함수가 중복 생성되어 코드가 지저분해질 수 있다.

  • 재귀로 만들 경우에 부적합하다.
    람다식 안에서는 람다식을 가리키는 변수를 참조할 수가 없기 때문에 재귀 람다식의 호출이 까다롭다.

  • 호출을 위해 직접 메소드를 불러야 한다.
    람다식을 생성하여 다른 함수의 파라미터로 전달하는 것은 자연스럽지만,
    람다식을 실행할 때에는 인터페이스에 선언된 메소드를 호출해야 한다.


함수형 인터페이스

@Functional Interface
'구현해야 할 추상 메소드가 하나만 정의된 인터페이스'
즉, 추상 메서드가 오직 하나인 인터페이스

🟡 함수형 인터페이스란?

함수를 1급 객체처럼 다룰 수 있게 해주는 어노테이션.
인터페이스에 선언하여 단 하나의 추상 메소드만을 갖도록 제한하는 역할을 한다.
함수형 인터페이스를 사용하는 이유는 Java의 람다식이 함수형 인터페이스를 반환하기 때문이다.

🟡 등장 이유

람다식으로 순수 함수를 선언할 수 있게 되었지만 Java는 기본적으로 객체지향 언어이기 때문에 순수 함수와 일반 함수를 다르게 취급하고 있다.
때문에, Java에서는 이를 구분하기 위해 함수형 인터페이스가 등장하게 되었다.
람다식은 함수형 인터페이스로만 접근이 되기 때문에 사용하기 위해서는 함수형 인터페이스가 필요하다.

🟡 구현

@FunctionalInterface
interface CustomInterface<T> {
    // abstract method 오직 하나
    T myCall();

    // default method 는 존재해도 상관없음
    default void printDefault() {
        System.out.println("Hello Default");
    }

    // static method 는 존재해도 상관없음
    static void printStatic() {
        System.out.println("Hello Static");
    }
}

🟡 특징

  • 한 개의 추상메소드만 가지고 있어야 한다.
    여러 개의 디폴트 메서드가 있더라도 추상 메서드가 오직 하나면 함수형 인터페이스이다.

  • 자바의 람다식은 함수형 인터페이스로만 사용 가능하다.

  • 자바 컴파일러는 이렇게 명시된 함수형 인터페이스에 두 개 이상의 메소드가 선언되면 오류를 발생시킨다.

  • @FunctionalInterface 어노테이션을 사용한다.
    : 이 어노테이션은 해당 인터페이스가 함수형 인터페이스 조건에 맞는지 검사한다.
    : 이 어노테이션 없어도 함수형 인터페이스로 동작하고 사용하는 데 문제는 없지만, 어노테이션을 붙이지 않으면 컴파일러가 검증을 해주지 않기 때문에, 인터페이스 검증과 유지보수를 위해 붙여주는 게 좋다.

함수형 인터페이스 형식에 맞지 않을 경우 @FunctionalInterface 은 다음 에러를 띄워준다.
Multiple non-overriding abstract methods found in interface com.practice.notepad.CustomFunctionalInterface

🟡 자바 기본 제공 함수형 인터페이스

  • Runnable
  • Supplier
  • Consumer
  • Function<T, R>
  • Predicate

cf)
// 람다식
https://mangkyu.tistory.com/113
https://blog.naver.com/PostView.naver?blogId=hj_kim97&logNo=222318922263&redirect=Dlog&widgetTypeCall=true&topReferer=https%3A%2F%2Fwww.google.com%2F&directAccess=false
// 함수형 인터페이스
https://bcp0109.tistory.com/313

profile
례코드

0개의 댓글