익명 클래스 를 더 간결하게 표현하는 문법
함수형 인터페이스 를 통해서 구현하는 것을 권장(a, b) -> a + b 표현식을 보고, sum() 메소드를 가진 익명 클래스를 구현함Calculator 인터페이스에 추상 메소드가 하나뿐이기 때문에(a, b) -> a + b 람다 표현식이 sum() 메소드라고 추론함interface IAdd {
int add(int x, int y);
}
class Add implements IAdd {
public int add(int x, int y) {
return x + y;
}
}
public class Main {
public static void main(String[] args) {
// 생 클래스로 메소드 사용하기
Add a = new Add();
int result1 = a.add(1, 2);
System.out.println(result1);
}
}
add() 메소드 사용interface IAdd {
int add(int x, int y);
}
public class Main {
public static void main(String[] args) {
// 익명 클래스로 정의해 사용하기 (일회용)
Iadd a = new IAdd() {
public int add(int x, int y) {
return x + y;
}
};
int result2 = a.add(1, 2);
System.out.println(result2);
}
}
@FunctionalInterface
interface IAdd {
int add(int x, int y);
}
public class Main {
public static void main(String[] args) {
// 람다 표현식으로 함축 하기
IAdd lambda = (x, y) -> {
return x + y;
}; // 람다식 끝에 세미콜론을 잊지말자
int result3 = lambda.add(1, 2);
System.out.println(result3);
}
}
아무 클래스나 추상 클래스의 메소드를 람다식으로 줄이는 등의 행위는 못한다.
오로지 인터페이스로 선언한 익명 구현 객체만이 람다식으로 표현할 수 있다.
그리고 람다 표현이 가능한 인터페이스를 가리켜 함수형 인터페이스라 한다.
⚠️ 람다 사용 시 주의사항
꼭
함수형 인터페이스어노테이션을 활용합시다.
함수형 인터페이스는 단 하나의 추상 메서드만 가지도록 강제하는 어노테이션입니다.- 인터페이스에 두 개 이상의 추상 메서드가 존재하면 컴파일러가 어떤 메서드를 구현하는지 모호해지기 때문입니다.
- 같은 이름의
sum()메서드를 여러 형태로 정의한다면
람다 표현식이 어떤 메서드를 구현하는 것인지 명확하지 않아
모호성이 발생할 수 있습니다.// 함수형 인터페이스가 될 수 있음 public interface Calculator { int sum(int a, int b); }// 함수형 인터페이스가 될 수 없음 public interface Calculator { int sum(int a, int b); int sub(int a, int b); }@FunctionalInterface // ✅ 함수형 인터페이스 선언 public interface Calculator { int sum(int a, int b); // ✅ 오직 하나의 추상 메서드만 선언해야합니다. int sum(int a, int b, int c); // ❌ 선언 불가. 에러발생! }
public class Main {
public static int calculate(int a, int b, Calculator calculator) {
return calculator.sum(a, b);
}
public static void main(String[] args) {
Calculator cal = new Calculator() {
@Override
public int sum(int a, int b) {
return a + b;
}
};
// ✅ 익명 클래스를 변수에 담아 전달
int ret = calculate(3, 3, cal);
System.out.println("ret = " + ret); // 출력: ret1 = 6
}
}
calculate() 메소드의 매개변수 타입이 Calculatorpublic class Main {
public static int calculate(int a, int b, Calculator calculator) {
return calculator.sum(a, b);
}
public static void main(String[] args) {
Calculator cal = (a, b) -> a + b;
// ✅ 람다식을 변수에 담아 전달
int ret = calculate(4, 4, cal);
System.out.println("ret = " + ret); // 출력: ret4 = 8
}
}
calculate() 메소드의 매개변수 타입이 Calculatorpublic class Main {
public static int calculate(int a, int b, Calculator calculator) {
return calculator.sum(a, b);
}
public static void main(String[] args) {
Calculator cal = (a, b) -> a + b;
// ✅ 람다식을 변수에 담아 전달
int ret = calculate(4, 4, cal);
System.out.println("ret = " + ret); // 출력: ret4 = 8
}
}
람다식의 가장 큰 특징은 변수에 정수를 할당하듯이 함수를 할당할 수 있다는 것이다.
함수도 일반 데이터처럼 메모리 주소가 할당되어 있다.
지금까지 클래스를 통해 메소드를 사용해왔기에 메모리 주소를 변수에 할당하는 일은 없었지만, 람다식을 사용하면 C 같은 함수 스타일의 프로그래밍이 가능해진다.
interface IAdd {
int add(int x, int y);
}
public class Main {
public static void main(String[] args) {
IAdd lambda = (x, y) -> x + y; // 함수를 변수에 할당
lambda.add(1, 2); // 함수 사용
}
}
특히 람다식은 메소드의 매개변수에 바로 입력값으로 넣는 방식으로 정말 많이 사용된다.
interface IAdd {
int add(int x, int y);
}
public class Main {
public static void main(String[] args) {
int n = result((x, y) -> x + y); // 메소드의 매개변수에 람다식을 전달
System.out.println(n); // 3
}
public static int result(IAdd lambda) {
return lambda.add(1, 2);
}
}
기존의 메소드같은경우 변수에 할당하거나, 매개변수로 넣거나, 반환값으로 사용하는 행위는 꿈도 못 꿔왔을 것이다.
하지만 람다식이 이런 식으로 응용이 가능한 이유는 람다는 익명 함수이며, 익명 함수는 모두 일급 객체로 취급되기 때문이다.
interface IAdd {
int add(int x, int y);
}
public class Main {
public static void main(String[] args) {
IAdd func = makeFunction(); // 메소드의 반환값이 람다 함수
int result = func.add(1, 2);
System.out.println(result); // 3
}
public static IAdd makeFunction() {
return (x, y) -> x + y;
}
}
챕터 3-5 : 람다(Lambda)
람다 표현식 완벽 정리