람다식이란
람다식이란 간단히 말해 메소드를 하나의 '식'(expression) 으로 표현한 것이다.람다식은 함수를 간략하면서도 명확하게 표현할 수 있다는 장점이 있다. 메소드를 람다식으로 표현하면, 메소드 이름, 반환타입이 없어지므로 익명함수(Anonymous Function)이라고도 부른다.예를들어 아래와 같이 사용할 수 있다.
int[] arr = new int[5];
Arrays.setAll(arr,(i) -> (int)(Math.random() * 5) + 1);
람다식 작성하기
람다식의 기본 형태는 아래와 같이 생겼다
(매개변수 선언) -> {문장들}
다만 여기서 반환값이 있는경우에서 두가지 경우로 작성해줄 수 있다.
- return문을 포함한 람다식 (statement가 된다. ;를 붙여야 된다. {}를 꼭 써주어야한다.)
(int a, int b) -> {return a > b ? a : b;}
2. return문을 포함시키지 않은 람다식(expression이 된다. ; 를 붙이지 않아도 됨. {}를 써주면 안된다.)
(int a, int b) -> a > b?a:b
statement형태의 람다식에서 {}를 생략할 수 있는 경우는 문장이 하나인 경우, 생략할 수 있다.
@FunctionalInterface
interface MyFunction1{
void myMethod();
}
MyFunction1 f1 = () -> System.out.println("Hello World"); // ok
다만 return문은 하나의 문장이어도 생략해서는 안된다.
@FunctionalInterface
interface MyFunction{
int max(int a, int b);
}
(int a, int b) -> return a>b ? a : b // Error
(int a, int b) -> {return a>b ? a : b;} // ok
함수형 인터페이스
람다식은 그렇다면 어떤 참조타입을 가질까? 람다식 또한 참조형이므로, 클래스, 인터페이스 모두 가능하다. 단, 람다식과 동일한 메소드가 정의되어있어야 하는것이다. 그래야만 참조변수로 익명 객체의 메소드를 호출할 수 있기 때문이다. 예를 들어 아래와같은 인터페이스가 있다고 가정하자
interface MyFunction{
int max(int a, int b);
}
이 인터페이스를 구현한 익명 클래스 객체는 다음과 같이 생성할 수 있는것이다.
MyFunction f = new MyFunction() {
@Override
public int max(int a, int b) {
return a > b?a:b;
}
};
int c = f.max(10,20);
인터페이스에 정의된 람다식 선언부와 max()의 선언부가 일치한다. 이를 람다식으로 아래와 같이 표현할 수도 있다.
class t{
public static void main(String[] args){
MyFunction f = (int a, int b) -> {return a>b ? a : b;};
int c = f.max(10,20);
}
}
인터페이스를 구현한 익명 객체를 람다식으로 대체가 가능한 이유는
- 람다식도 실제로는 익명객체이다
- 익명객체 메소드와 람다식의 매개변수타입, 개수, 반환값이 모두 일치하다
와 같은 이유로 대체가 가능하다. 이와 같은 이유로 인터페이스를 통해 람다식을 다루기로 결정하였으며, 람다식을 다루기 위한 인터페이스를 '함수형 인터페이스' 라고 부르기로 했다. 함수형 인터페이스 선언은 인터페이스 위에 어노테이션 '@FunctionalInterface'를 붙여주면된다.
@FunctionalInterface
interface MyFunction1{
void myMethod();
}
단, 이 함수형 인터페이스는 '오직 하나의 추상메소드만 정의되어있어야 한다' 라는 제약이 있다. 이유는, 이래야 람다식, 인터페이스 메소드가 1 : 1 매핑이 되기 때문이다.
함수형 인터페이스 타입의 매개변수와 반환타입
아래와 같은 함수형 인터페이스가 정의되어있다고 가정하자
@FunctionalInterface
interface MyFunction1{
void myMethod();
}
만약 메소드 매개변수가 함수형 인터페이스인 MyFunction1이면 어떻게 해야할까? 이는 이 메소드를 호출할 때 람다식을 참조하는 참조변수를 매개변수로 지정해야한다는 의미이다. 아래와 같이 MyFunction1타입 매개변수를 받는 aMethod라는 메소드가 있다고 가정하자
class lambda_test{
void aMethod(MyFunction1 f){
f.myMethod();
}
}
이 메소드에는 아래와 같이 두가지 방법으로 넘겨줄 수 있다. 하나는 함수형 인터페이스를 구현한 참조변수를 넘겨줄 수 도 있고, 다른 한 방법은 직접 익명함수를 넘겨주는 방법도 있다.
class t{
public static void main(String[] args){
lambda_test lt = new lambda_test();
// 방법 1
MyFunction1 f = () -> System.out.println("Hello World");
lt.aMethod(f);
//방법 2
lt.aMethod(() -> System.out.println("Hello World"));
}
}
그리고 반대로 반환타입이 함수형 인터페이스인 경우를 살펴보자. 이런 경우에도 위와 동일하게 함수형 인터페이스를 구현한 참조변수를 반환해도 되고 식을 직접 반환해도 된다.
class lambda_test{
MyFunction1 getMyFunction1_1(){
MyFunction1 f = () -> System.out.println("Hello Wolrd");
return f;
}
MyFunction1 getMyFunction1_2(){
return () -> System.out.println("Hello World");
}
}
'Language > Java' 카테고리의 다른 글
[Java] Comparator, Comparable (0) | 2022.05.20 |
---|---|
[Java] Maven설치하기(M1 mac) (0) | 2022.03.01 |
[Java]제네릭스(Generics) (0) | 2022.02.16 |
[Java] Collection FrameWork (0) | 2022.02.08 |
[Java] 컬렉션 프레임워크(Collection Framework) (0) | 2022.01.25 |