람다식?
람다식(Lambda expression)은 자바에서 제공하는 함수형 프로그래밍 방식이다. (함수형 프로그래밍은 함수의 구현과 호출만으로 프로그램을 만드는 프로그래밍 방식이다)
람다식을 간단하게 설명하자면 이름이 없는 익명 함수를 만드는 것이다. 예시를 통해 람다식에 대해 알아보자.
//두 정수를 매개변수로 받아 두 수의 합을 반환하는 함수
//일반적인 함수 선언
int add(int a, int b) {
return a + b;
}
//람다식을 이용한 함수 선언
(int a, int b) -> {return a + b;}
람다식을 보면 소괄호('()') 안에 함수에서 사용될 매개변수가 들어가고, 중괄호('{}') 안에 함수에서 수행할 로직이 들어간다. 그리고 일반적인 함수 선언 방식과 비교하면 함수의 이름이 존재하지 않는다.
람다식 문법
람다식 표현에서 컴파일러가 매개변수를 추론할 수 있는 경우, 매개변수의 타입을 생략할 수 있다.
(String str) -> {System.out.println(str);}
(str) -> {System.out.println(str);}
두 표현은 동일한 표현이다.
그리고 특별한 경우에 소괄호 또는 중괄호를 생략할 수 있다.
//매개변수가 하나인 경우 소괄호 생략 가능
(str) -> {System.out.println(str);}
str -> {System.out.println(str);}
//중괄호 안의 구현 부분이 한 문장인 경우 중괄호 생략 가능. (단, return문일 경우 중괄호 생략 x)
str -> {System.out.println(str);}
str -> System.out.println(str);
str -> return str.length(); (x)
//중괄호 안의 구현 부분이 한 문장이고, return 문인 경우는 중괄호와 return 모두 생략가능
str -> {return str.length();}
str -> str.length();
지금까지 한 내용을 정리해 보자. 람다식은 익명 함수를 표현하는 방법이란 걸 알았고, 람다식의 문법에 대해 정리해 봤다. 그럼 자바에서는 람다식을 이용해 어떻게 함수형 프로그래밍 방식처럼 프로그래밍 할 수 있을까?
람다식 사용하기
람다식은 메서드 이름이 없고 메서드를 실행하는데 필요한 매개변수와 매개변수를 활용한 실행 코드를 구현하는 것이다. 그럼 메서드는 어디에 선언하고 구현해야 할까? 함수형 언어의 경우는 함수만 호출할 수 있지만 자바는 그렇지 않다. 자바에서 메서드를 호출하기 위해서는 참조 변수가 필요하고 참조 변수를 통해 함수(메서드)를 호출할 수 있다.
람다식을 이용하기 위해서는 인터페이스를 만들고 인터페이스에 람다식으로 구현할 메서드를 선언해야 한다. 다음 예시를 보자.
public interface Hello {
void hello(String str); //람다식으로 구현할 메서드
}
public class javaMain {
public static void main(String[] args) {
Hello hello = str -> System.out.println(str + " Hello!"); //람다식을 저장
hello.hello("hyuk");
}
}
Hello 인터페이스의 hello 메서드에 람다식으로 표현한 함수를 저장했다.
람다식을 사용하면 좋은점?
그럼 람다식을 왜 사용하는걸까? 일단 예시를 통해 느껴보자. 위에서 진행한 예시를 객체 지향적인 방법으로 해결해보자.
public interface Hello {
void hello(String str);
}
public class HelloImpl implements Hello {
@Override
public void hello(String str) {
System.out.println(str + " Hello!");
}
}
public class javaMain {
public static void main(String[] args) {
Hello hello = new HelloImpl();
hello.hello("hyuk");
}
}
사용하고 싶은 함수를 만들기 위해서 다음과 같은 과정이 필요하다.
- 인터페이스의 구현 객체 만들기.
- 구현 객체에 원하는 메서드 선언하고 구현하기.
- 함수를 사용하고 싶을 때 구현 객체를 생성해 함수를 사용하기
원하는 기능을 구현한 함수를 사용하기 위해 객체 지향적으로 코드를 작성하면 부수적인 일(클래스 선언, 구현)을 해야한다. 하지만 람다식을 이용하면 그러한 작업 없이 필요한 함수를 만들고 사용할 수 있다.
함수형 인터페이스
위와 같이 람다식을 이용해 함수를 저장하고 사용하기 위한 인터페이스를 함수형 인터페이스라고 한다.
@FunctionalInterface
public interface Hello {
void hello(String str);
}
인터페이스를 함수형 인터페이스로 사용하고 싶은 경우 @FunctionalInterface 어노테이션을 사용해도 되고, 사용하지 않아도 된다. 하지만 사용하면 몇 가지 장점이 있다.
- 해당 인터페이스가 함수형 인터페이스임을 명시적으로 알 수 있다.
- 컴파일 시점에서 함수형 인터페이스에 여러 함수가 선언되면 오류를 잡아준다. (함수형 인터페이스는 람다식을 이용해 함수를 저장하기 위한 인터페이스이다. 따라서 인터페이스에 함수가 2개 이상 선언되면, 람다식으로 구현한 함수를 어디에 저장해야 할지 모르기 때문에 오류가 발생한다. )
람다식의 동작원리
람다식을 함수형 인터페이스를 이용해 저장하고, 사용했는데 이게 과연 자바 내부적으로 어떻게 동작될까? 자바는 객체 지향언어이다. 따라서 우리가 간단하게 람다식을 함수형 인터페이스에 저장해도, 자바는 내부적으로 익명 객체를 생성해 준다.
//함수형 인터페이스에 람다식을 할당.
Hello hello = str -> System.out.println(str + " hello");
//위의 코드가 실제 동작되는 과정
Hello hello = new Hello() {
@Override
public void hello(String str) {
System.out.println(str + " hello");
}
};
람다식의 이용
우리가 람다식을 이용하면 구현된 함수를 변수처럼 사용할 수 있다. 따라서 다음 세 가지 작업을 할 수 있다.
- 람다식을 변수에 대입하기.
- 람다식을 매개변수로 넘기기.
- 람다식을 반환값으로 받기.
람다식을 변수에 대입하기
Hello hello = str -> System.out.println(str + " hello");
인터페이스형 변수를 선언하고, 람다식을 대입했다.
람다식을 매개변수로 넘기기
public class javaMain {
public static void main(String[] args) {
Hello hello = str -> System.out.println(str + " hello");
example(hello);
}
public static void example(Hello hello) {
hello.hello("hyuk");
}
}
인터페이스형 변수에 람다식을 저장한 뒤, 해당 변수를 함수의 매개변수로 넘겼다.
람다식을 반환값으로 받기.
public class javaMain {
public static void main(String[] args) {
Hello hello = getLambda();
hello.hello("hyuk");
}
public static Hello getLambda() {
Hello hello = str -> System.out.println(str + " hello");
return hello;
}
}
위와 같이 함수를 변수처럼 사용할 수 있는 게 함수형 프로그래밍의 특징 중 하나이다.
정리
람다식은 익명 함수를 만들어주는 식이다.
그리고 우린 람다식을 이용해 만든 익명 함수를 함수형 인터페이스를 이용해 저장하고, 매개변수로 이용하고, 반환값으로 사용할 수 있다.
즉 객체 지향 언어인 자바에서 람다식과 함수형 인터페이스를 이용해 함수형 언어처럼 프로그래밍 할 수 있다.
reference
Do it 자바 프로그래밍 입문
'Java' 카테고리의 다른 글
Java 시간관련 객체 정리 (0) | 2024.03.09 |
---|---|
익명 클래스 (0) | 2022.05.15 |
Iterator (0) | 2022.04.24 |