[Java] lambda 기본 개념
Lambda
```java
// 기본 형식. 2줄 이상일 때
( parameters ) -> { expression body }
// 별다른 내용 없이 바로 return할 수 있는 경우
( parameters ) -> expression
```
Lambda를 활용한 Thread
보통 자바에서 Thread는 다음과 같이 Thread로 사용할 class에 Runnable interface를 implements하여 Thread객체에 파라미터로 전달하여 사용한다.
```java
class TestThread implements Runnable {
@Override
public void run() {
System.out.println("newTHread");
}
}
```
```java
Thread t = new Thread(new TestThread());
t.start();
```
그러나 Runnable interface를 무명 클래스로 바로 구현해서 사용하는 경우도 있다.
```java
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("inner");
}
}).start();
```
Runnable interface는 함수형 인터페이스이기 때문에 이 경우 람다식을 사용할 수 있다.
```java
new Thread(()->{
System.out.println("lambda");
}).start();
```
이같은 방법을 이벤트 핸들러 등 코드가 지저분해지는 구간에 적용하면 말끔하게 처리 가능하다.
Functional Interface
- ``java new Runnable()...``을 람다로 대체 할 수 있었던 것은, Runnable이 함수형 인터페이스 이기 때문이다.
- 함수형 인터페이스는 바디가 없는 메서드(추상 메서드)를 하나만 가지고 있는 인터페이스를 말한다.
- 인터페이스이므로 new를 통해 추상 메서드를 구현해준다면 익명 객체로 만들 수 있다.
- default method는 바디가 있기 때문에 추상 메서드가 아니므로 여러 개 가질 수 있다.
- 함수형 인터페이스는 바디가 없는 메서드(추상 메서드)를 하나만 가지고 있는 인터페이스를 말한다.
- 람다를 넘기는게 함수가 넘어가는 것 처럼 보이지만 사실은 파라미터 타입에 알맞은 익명 객체를 만들고, 람다 함수를 이 익명 객체의 추상 메서드 바디에 할당하여 넘기는 것이다.
- 자바에서 함수는 일급 시민이 아니기 때문에, 어쨌든 넘어가는건 객체다.
- 이 익명 객체의 원형이 되는 클래스는 반드시 추상 메서드를 하나만 가지고 있어야 한다. 즉, 함수형 인터페이스 여야 한다.
- 이는 객체를 만들면서 람다 함수를 추상 메서드 바디에 할당해야 하는데 추상 메서드가 여러 개 있으면 람다를 어떤 메서드에 대응시켜야 할지 알 수 없기 때문이다.
- 람다 함수가 추상 메서드 바디에 할당된다는건, 평소 익명 객체를 바로 구현해서 사용할 때 생각해보면 된다. 거기서 필요없는거 다 빼고 메서드 파라미터와 바디만 남겨놓은게 람다다.
- 결국 함수를 담은 객체가 넘어가는 것이기 때문에, 함수형 인터페이스 변수에 함수를 담아 넘기거나 리턴할 수 있다.
- ``java @FunctionalInterface`` annotation
- 붙이면 추상 메소드가 두 개 이상일 때 컴파일 오류로 알려준다.
- 함수형 인터페이스 임을 명시하는 효과도 있으므로 사용하면 좋다.
- StreamAPI의 filter나 map에 넘어오는 람다는 Predicate, Function 이라는 표준 함수형 인터페이스다.
직접 정의하는 경우?
```java
@FunctionalInterface
interface VItoI{
public int out(int... a);
}
```
```java
VItoI add = (int... a) -> {return a[0] + a[1];};
VItoI mul = (int... a) -> a[0] * a[1];
System.out.println(add.out(1, 3));
System.out.println(mul.out(1, 2));
```
add, mul은 interface 객체이기 때문에 그 내부에 구현한 method "out"을 호출해줘야 한다.
메서드 참조 (Method References)
람다를 메서드 참조로 대신할 수 있음. ``java BigInteger::nextProbablePrime``
'Java Stack > Java' 카테고리의 다른 글
[Java] LocalDateTime : 날짜 시간 처리 관련 (0) | 2019.07.10 |
---|---|
[Java] Enum (0) | 2019.06.06 |
[Java] Jackson ObjectMapper Serialization (0) | 2019.05.15 |
JVM 관련 (0) | 2017.05.05 |
[Java] Stream API 노트 (0) | 2017.03.09 |