엄범

 

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``

 

'Languages & Frameworks > Java' 카테고리의 다른 글

[Effective Java] 3장 모든 객체의 공통 메서드  (0) 2019.12.04
[Effective Java] 2장 객체 생성과 파괴  (0) 2019.12.02
[java] 날짜 시간 처리 관련  (0) 2019.07.10
[Java] Enum  (0) 2019.06.06
[Java] Stream API 노트  (0) 2017.03.09
[Java] lambda 기본 개념  (0) 2017.02.07