예전에는 자바에서 함수 타입을 표현할 때 추상 메서드를 하나만 담은 인터페이스를 사용했고 이런 인터페이스의 인스턴스를 함수 객체(function object)라 해서, 특정 함수나 동작을 나타내는대 사용했다.
함수 객체를 만드는 방식으로는 익명 클래스를 주로 사용했다. 하지만 익명 클래스는 너무 길기 때문에 함수형 프로그래밍에 적합하지 않았다. 자바 8에 와서야 람다가 도입되 함수 객체를 람다를 통해 짧은 길이로도 만들 수 있게 되었다. 람다는 함수나 익명 클래스와 개념은 비슷하지만 코드는 훨신 간결하다.
람다의 매개변수와 반환값은 컴파일러가 타입 추론을 사용해 추론하기 때문에 통상적인 상황에서는 타입을 명시하지 않아도 된다. 그럼에도 타입을 명시해야 코드가 더 명확할 때에는 타입을 명시해야 한다.
람다를 언어차원에서 지원하면서 기존에는 적합하지 않던 곳에서도 함수 객체를 사용할 수 있게 되었다. 예컨데, enum의 상수별로 다르게 동작하는 코드를 다음과 같이 람다를 활용해 작성할 수 있다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
public enum Operation {
PLUS("+") {
public double apply(double x, double y) {
return x + y;
}
}
...
}
// 람다 적용
public enum Operation {
PLUS("+", (x, y) -> x + y);
...
}
|
cs |
하지만 무조건 익명 클래스 대신 람다를 사용하라는 의미는 아니다. 람다는 이름이 없고 문서화도 못한다, 따라서 코드 자체로 동작이 명확히 설명되지 않거나 코드 줄 수가 많아지면 람다를 쓰지 말아야 한다. 람다는 가독성을 위해 최대 세 줄을 넘어가지 말아야 한다.
열거타입 생성자에 넘겨지는 인수들의 타입은 컴파일타임에 추론된다. 따라서 열거 타입 생성자 안의 람다는 열거타입의 인스턴스 멤버에 접근할 수 없다.(인스턴스는 런타임에 만들어 진다)
람다는 함수형 인터페이스에서만 쓰이기 때문에 추상 클래스의 인스턴스를 만들 때나 추상 메서드가 여러 개임 인터페이스의 인스턴스를 만들 때는 익명 클래스를 사용해야 한다.
람다는 자신을 참조할 수 없다. 람다에서의 this 키워드는 바깥 인스턴스를 가리킨다. 반면 익명 클래스에서의 this는 익명 클래스의 인스턴스 자신을 가리킨다. 따라서 함수 객체가 자신을 참조해야 한다면 익명 클래스를 사용하라.
출처 - 이펙티브 자바