람다식은 익명 함수를 생성하기 위한 것으로 자바8 부터 등장하게 되었습니다. 객체 지향 언어인 자바에서 함수 지향에 가까운 람다식을 사용할 수 있게 된 것이죠. 람다식을 사용할 때의 장점은 코드가 간결해지고, 함수형 프로그래밍의 이점을 가져올 수 있기 때문입니다. 사용 이유가 가장 중요하기 때문에 함수형 프로그래밍을 조금 알아보고 갈까요?
Functional Programming is programming without assignment satements
클린코드 책에서는 함수형 프로그래밍을 이렇게 정의하고 있습니다. 즉 대입문이 없는 프로그래밍이라는 것인데요. 자바처럼 객체 지향, 명령형 프로그래밍에서는 함수에 값을 대입할 수 있습니다. 그렇기 때문에 대입되는 값에 따라 전혀 다른 결과가 나오기도 합니다. 반면에 함수형 프로그래밍은 선언문이 없기 때문에 함수가 다른 결과를 반환할 일이 없습니다. 그렇기 때문에 함수들이 독립적이고 multi-tread 환경에서 안전하게 동작할 수 있습니다. 이러한 특징을 사용하고자 람다식을 사용하게 된 것이죠. 함수형 프로그래밍에 대해서는 얄코님의 함수형 프로그래밍이 뭔가요? 영상을 보시면 쉽게 이해하실 수 있을 것 같습니다.
(변수) -> {실행문;}
(String message) -> {System.out.println(message);}
(message) -> {System.out.println(message);} //변수의 타입 생략 가능
message -> {System.out.println(message);} //변수가 하나일 때 괄호 생략 가능
message -> System.out.println(message) //실행문이 하나일 경우 대괄호 생략 가능
실제 코드에서 예시를 보면 Runnable 인터페이스의 익명 객체를 구현할 때 람다식을 사용하여 코드를 간결하게 만들 수 있습니다.
Runnable runnable = new Runnable() {
@Override
public void run() {
System.out.println("익명 객체 구현");
}
};
Runnable runnable = () -> System.out.println("익명 객체 구현");
IntelliJ와 같은 IDE에서도 람다식을 사용하길 권장하고 있으며 실제로 변경 시에 코드가 깔끔한 것을 확인할 수 있습니다.
람다식으로 표현한 코드를 보면 이름이 없는, 즉 익명의 함수가 Runnable 인터페이스를 구현한 runnable 객체에 대입이 되는 것처럼 보입니다. 마치 함수를 변수처럼 사용할 수 있는 것이죠.
Runnable 인터페이스는 run 이라는 함수 하나만 가지고 있는 인터페이스입니다. 위의 예시에서 람다를 통하여 하나의 익명 객체를 만들었는데 만약 구현해야할 함수가 2개가 있다면 람다식이 어떤 함수를 익명 함수로 구현하고 있는지 알 수가 없습니다. 이렇게 하나의 추상 함수만을 가지고 있는 인터페이스를 함수형 인터페이스라고 합니다. Runnable 인터페이스도 함수형 인터페이스로 구현이 되어 있습니다.
@FunctionalInterface
public interface Runnable {
void run();
}
@FunctionalInterface라는 annotaion을 붙여 함수형 인터페이스라는 것을 선언하고 있습니다. 이 이노테이션은 만약 2개의 추상 함수를 구현할 경우 컴파일 시 오류를 내주기 위한 일종의 안전장치로 없다고 함수형 인터페이스가 되지 않는 것은 아닙니다. 또한 추상 메소드 이외에 dafualt, static으로 정의된 함수들은 개수에 포함되지 않으니 추가적으로 구현하여도 문제가 되지 않습니다.
람다식은 Stream과 함께 쓰일 때 더 큰 효과를 가질 수 있습니다. 다음 시간에는 Stream에 대해 알아보겠습니다.
[Java] equals() & hashCode() (0) | 2023.03.01 |
---|