// 람다식이 적용되지 않은 Method
int method() {
return (int)(Math.random() * 5) + 1;
}
// 람다식이 적용된 Method
Arrays.setAll(arr, (i) -> (int)(Math.random() * 5) +1);
람다식이 적용되지 않았을때보다 람다식이 적용되었을때가 간결하고 이해하기 쉽다.
// 람다식 적용 전
int max(int a, int b) {
return a > b ? a : b;
}
// 람다식 적용 후 - return문 사용
(int a, int b) -> {return a > b ? a : b}
// 람다식 적용 후 - 식(expression) 사용
(int a, int b) -> a > b ? a : b
반환값이 있는 메서드의 경우, return문 대신 식(expression)으로 대체 가능하다.
문장이 아닌 식이기 때문에 끝에 ";"를 붙이지 않아야 한다.
람다식에 선언된 매개변수의 타입은 추론이 가능한 경우 생략이 가능하다.
// 람다식 타입 생략 전
(int a, int b) -> a > b ? a : b
// 람다식 타입 생략 후
(a, b) -> a > b ? a : b
// 람다식 타입 생략 에러 CASE
(int a, b) -> a > b ? a : b
맨 마지막 에러 CASE와 같이 두 매개변수 중 어느 하나의 타입만 생략하는 것은 허용되지 않는다.
아래와 같이 선언된 매개변수가 하나라면, 괄호( )를 생략할 수 있다.
// 괄호 생략 전
(a) -> a * a
(int a) -> a * a
// 괄호 생략 후
a -> a * a // OK
int a -> a * a // 에러
매개변수의 타입이 있는 경우에는 괄호를 생략할 수 없다.
괄호{ }안의 문장이 하나일 때는 괄호{ }를 생략할 수 있다. 이 때 문장의 끝에는 ' ; '을 붙이지 않아야 한다.
// 괄호 생략 전
(String name, int i) -> {
System.out.println(name + "=" + i);
}
// 괄호 생략 후
(String name, int i) ->
System.out.println(name + "=" + i)
괄호 { } 안의 문장이 return문일 경우에는 괄호{ } 생략이 불가능하다.
(int a, int b) -> { return a > b ? a : b; } // OK
(int a, int b) -> return a > b ? a : b // ERROR
람다식은 익명 클래스의 객체와 동등하다.
interface MyFunction {
public abstract int max(int a, int b);
}
위와 같은 max( )라는 메서드가 정의된 MyFunction 인터페이스가 정의 되어 있다고 가정한다면
이 인터페이스를 구현한 익명 클래스의 객체는 아래와 같이 생성할 수 있다.
MyFunction f = new MyFunction() {
public int max(int a, int b) {
return a > b ? a : b;
}
}
// 익명 객체의 메서드를 호출
int big = f.max(5, 3);
Myfunction 인터페이스에 정의된 메서드 max( )는 선언부가 일치한다면, 람다식으로
대체가 가능하다. 아래 코드는 위 코드를 람다식으로 대체한 코드이다.
MyFunction f = (int a, int b) -> a > b ? a : b; // 익명 객체를 람다식으로 대체
int big = f.max(5, 3); // 익명 객체의 메서드를 호출
인터페이스를 구현한 익명객체를 람다식으로 대체하려면, 익명 객체의 메서드와 람다식의 매개변수의 타입 및 개수 반환값이 일치해야 한다.
그래서 인터페이스를 통해 람다식을 다루기로 결정되어, 람다식을 다루기 위한 인터페이스를 함수형 인터페이스(Functional interface) 라고 부른다.
@FunctionalInterface
interface MyFunction { // 함수형 인터페이스 MyFunction을 정의
public abstract int max(int a, int b);
}
함수형 인터페이스는 오직 하나의 추상 메서드만 정의되어 있어야 한다.
그래야만 람다식과 인터페이스의 메서드가 1:1로 연결될 수 있기 때문이다.
static 메서드와 default 메서드의 개수에는 제약이 없다.
@FunctionalInterface 애너테이션을 붙이지 않아도 에러가 발생하지는 않지만,
컴파일러가 함수형 인터페이스를 올바르게 정의하였는지 확인해주는 역할을 하므로,
붙이면 도움이 된다.