본문 바로가기

개발

java8과 lambda 의 사용법

람다 표현식은 메서드로 전달할수 있는 익명함수를 단순화 한것

특징

  • 익명 - 이름이 없으므로 익명이라고 표현
  • 함수 - 메서드 처럼 특정 클래스에 종속되지 않음.
  • 전달 - 람다를 메서드로 전달하거나 변수로 저장할수 있음
  • 간결성 - 익명클래스 처럼 많은 코드를  구현할 필요가 없음

한마디로 익명 클래스와 메서드의 단점을 버리고 장점만 조합해서 만든것이 람다이다.

람다는 람다 파라미터, 화살표, 람다 바디로 이루어져 있는데 (파라미터 ) ->  표현식;  이런식으로 구성된다.

 

람다를 언제 사용하는건가?

-> 함수형 인터페이스라는 문맥에서 람다 표현식을 사용 할수 있다.

 

함수형 인터페이스라는것을 알아야 하는데  자바 8의 특징중 하나가

[자바 8설계자는 이급시민을 일급 시민으로 바꾸는 기능을 추가 했다.

이급 시민이었던 함수를 일급값으로 넘겨주는 프로그래밍을 함수형 프로그래밍이라고 한다. ]

 

함수형 인터페이스는 정확히 하나의 추상 메서드를 지정하는 인터페이스이다.

추상 메서드가 하나인것에 대해 기억 해두자!

ex>추상 메서드가 하나인 함수형 인터페이스

pubilic interface Adder{
	int add(int a , int b);
}

 

람다 표현식으로 함수형 인터페이스의 추상 메서드 구현을 직접 전달할수 있다.

ex> 

Runnable r1  = ()  -> sout("hello world"); // sout 귀찮아서 생략..

public static void process(Runnable r){
          r.run();
}

process(r1);

이런 코드가 있다고 할 때

public static void process(Runnable r){
          r.run();
}

process 보면 Runnable 을 파라미터로 받고 있다.

소스를 보면 process(r1); 이라는것이 있고 r1을 정의한것을 보면 람다로 정의 되어 있다.

람다를 process라는 메소드에 파라미터로 넘긴 걸 보면

아까도 강조한 [이급 시민이었던 함수를 일급값으로 넘겨주는 프로그래밍을 함수형 프로그래밍]을 하고 있는것이다.

 

또 r1에는 process 안에 있는 run() 이라는  추상 메서드가 있겠구나 유추 할 수 있다.

(람다 형식인 r1 을 넘겼으니 Runnable은 함수형 인터페이스고, 함수형 인터페이스는

정확히 하나의 추상 메서드를 가지고 있다.)

 

또 여기서 함수형 인터페이스는 왜 하나의 추상 메서드만 가지고 있어야 하나 생각해보면

추상 메서드가 2개라면 람다로 정의 할때 ()  -> sout("hello world"); 이때 이게

어떤 추상 메서드에서 사용하는것인지 알수 없기 때문이 아닐까 싶다.

 

하나의 추상메서드만 정의 해야 람다로 정의 할때 이름을 지정하지 않아도 자동으로 동작되는게 이런 이유인것 같다.

 

함수형 인터페이스 사용

. Predicate 인터페이스

boolean test(T t);

. Consumer 인터페이스

void accept(T t);

.Function 인터페이스

R apply(T t);

 

지역 변수 사용

. 람다 표현식에서는 익명함수가 하는것 처럼 자유 변수를 활용할수 있다.

람다는 인스턴스 변수와 정적변수를 자유롭게 캡쳐 할 수 있다.

지역변수는 명시적으로 final로 선언되어 있어야 하거나 final로 선언된 변수와 똑같이 사용되어야 한다.

 

아래 소스는 컴파일 에러가 난다.

int port = 7333;

Runnanle r = () -> sout("port");

port = 8333;

 

왜 지역 변수에 이런 제약이 필요할까?

-> 인스턴스 변수는 힙에 저장, 지역변수는 스택에 저장 한다.

람다가 스레드에서 실행된다면 변수를 할당한 스레드가 사라져서 변수 할당이 해제 되었는데도

람다를 실행하는 스레드에서는 해당 변수에 접근하려할수 있다.

 

람다 스레드 -> 변수를 할당한 스레드에 접근 -> 스레드 접근 가능한 상황 -> 이상없음

람다 스레드 -> 변수를 할당한  스레드에 접근 -> 스레드 접근 불 가능한 상황 -> 이상

 

이러한 이유로 지역 변수로 직접 접근하는것이 아니라 지역 변수의 복사본을 전달하고

이 값이 바뀌지 않아야 하므로 지역 변수에는 한 번만 값을 할당 해야하는 이슈가 있다.