람다식은 Java 8 에서 추가된 내용이며 가장 큰 변화로서, 함수형 프로그래밍(Functional Programming)을 지원한다. 이전까지, 메소드만 단독으로 선언이 불가하였다. 그리고 자바에서 메소드는 일급객체(First-class Citizen)가 아니다. 아래는 일급객체가 가져야 하는 특성들이다.
- 변수나 데이타에 할당 가능
- 함수의 인자로 전달 가능
- 함수의 리턴값으로 리턴 가능
람다식은 인터페이스 참조 변수에 익명 클래스를 사용할 때 가능하다. 그리고 추상 메소드도 오직 1개만 가지고 있어야 한다. 대표적인 것이 Comparator 인터페이스이다. 아래는 그 예제이다.
Comparator<String> comp = new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return o1.compareTo(o2);
}
};
이 긴 코드가 아래와 같이 람다식을 사용하면 매우 간략하게 표현될 수 있다.
Comparator<String> compLambda = (o1, o2) -> o1.compareTo(o2);
- 단 1 개의 추상 메소드
- 여러개의 default, static 메소드 상관 없음
람다식을 사용하기 위한 조건은 인터페이스이면서 단 1 개의 Abstract Method 만 가지고 있으면 어떤 인터페이스라도 람다식을 사용 가능하다. 즉, 인터페이스에 여러개의 default method 나 static method 가 있어도 상관없다.
public interface MyFunction {
public String setName(String name);
default void greet(String str) {
System.out.println(str);
}
static void city(String time){
System.out.println("This is " + time);
}
}
위는 람다로 만들기 위해 정의한 인터페이스이다. 추상 메소드가 하나만 있는 것을 확인할 수 있다. 아래는 각 abstract, default, static method 들을 사용한 예시이다.
public class LambdaExamples {
public static void main(String[] args) {
// static method
MyFunction.city("Seoul");
// Lambda
MyFunction myFunction = name -> "Hello " + name;
System.out.println(myFunction.setName("Mr.Lee"));
// default
myFunction.greet("Nice to meet you");
}
}
이 결과는 아래와 같다.
This is Seoul
Hello Mr.Lee
Nice to meet you
기본적으로 람다식은 stateless 하다. 즉, 람다는 인터페이스를 활용하는 것이기 때문에 변수를 포함하고 있지 않다. 하지만, 람다식을 만들 때 외부의 변수를 람다식 내부에서 참조하도록 만들 수 있다.
여기서 주의할 점은 같은 메소드 스코프 내에 위치한 변수는 final 이어야 하지만, 이 스코프 이외의 영역에서 참조되는 변수들은 상관없다. 그리고 이 변수들은 심지어 값이 달라지면 이것이 람다식 내부에서도 변경되는 값이 반영된다.