상세 컨텐츠

본문 제목

[JAVA] - 람다식(Lambda Expressions)

Spring/JAVA

by Chan.94 2022. 7. 7. 18:16

본문

반응형

람다식이란?

JAVA8 버전부터 람다식(Lambda Expressions)을 지원하게 되었다.

람다식은 함수의 이름이 없기 때문에 익명 함수라고도 한다.


사용방법

(타입 매개변수, ...) -> {실행문; ...}

'(타입 매개변수, ...)'는 오른쪽 중괄호 블록을 실행하기 위해 필요한 값을 제공하는 역할을 하며, '->' 기호는 매개 변수를 이용해서 중괄호 블록을 실행한다고 이해하면 된다.

 

매개 변수의 타입은 런타임 시에 대입되는 값에 따라 자동으로 인식될 수 있기 때문에 매개 변수의 타입은 일반적으로 언급하지 않으며, 하나의 매개 변수만 존재할 때는 소괄호를 제거할 수 있다.

다만, 매개 변수가 없다면 소괄호를 반드시 붙여주어야 한다.

 

 중괄호를 실행하고 결과값을 리턴해야 한다면, 다음과 같이 return문을 작성하면 된다.

(x, y) -> {return x + y;};

자바에서 메소드를 작성하려면 접근 제한자, static 유무, 리턴 타입, 함수 이름, 매개 변수를 적어 주어야 하였는데 람다식을 사용하면 짧은 코드로 표현할 수 있다. 이것이 람다식의 최대 장점이다.

 

타겟 타입

자바는 메소드를 단독으로 선언할 수 없고 항상 클래스의 구성 멤버로 선언하기 때문에 람다식은 단순히 메소드를 선언하는 것이 아니라 이 메소드를 가지고 있는 객체를 생성해 낸다.

 

이 객체의 타입은 인터페이스이며 "인터페이스 변수 = 람다식;"과 같이 선언하여 사용한다. 즉, 람다식은 인터페이스의 익명 구현 객체를 생성한다는 말고 같다.

 

인터페이스는 직접 객체화할 수 없기 때문에 구현 클래스가 필요한데, 람다식은 익명 구현 클래스를 생성하고 객체화한다. 또한, 람다식은 대입될 인터페이스의 종류에 따라 작성 방법이 달라지기 때문에 람다식이 대입될 인터페이스를 람다식의 타겟 타입이라고 부른다.

 

함수적 인터페이스

위에서 람다식을 사용하기 위해서는 람다식이 대입될 인터페이스가 필요하다는 것을 알았다. 람다식을 구현하기 위한 인터페이스에는 조건이 하나 있다. 한 개의 추상메소드만 가지고 있어야 한다는 것이다. 이런 인터페이스를 하수적 인터페이스라고 부른다.@FunctionalInterface 어노테이션으로 이런 함수적 인터페이스를 명시할 수 있다.

@FunctionalInterface
public interface LambdaInterface {
	public int lambdaExpression(int a, int b);
}
public class LambdaImpl {

	public static void main(String[] args) {
		
		int nVar1 = 2;
		int nVar2 = 3;
		
		//타겟타입 : LambdaInterface
		LambdaInterface lambdaInterface = (a, b) -> {return a + b;};
		System.out.println(lambdaInterface.lambdaExpression(nVar1, nVar2));		// 5
		
		lambdaInterface = (a, b) -> {return a * b;};
		System.out.println(lambdaInterface.lambdaExpression(nVar1, nVar2));		// 6
		
	}

}

런타임 시에 메소드를 정의하여 사용할 수 있는 것을 확인할 수 있다.

 

람다식에서 지역변수 사용

람다식에서 지역 변수를 사용하면 final 특성을 가져야 한다. 람다식에서 읽는 것은 허용되지만, 람다식 내부 또는 외부에서 변경할 수 없다는 뜻이다.

public class LambdaImpl {

	public static void main(String[] args) {
		int nVar1 = 2;
		int nVar2 = 3;
		int nVar3 = 4;
		
		//타겟타입 : LambdaInterface
		LambdaInterface lambdaInterface = (a, b) -> {return a + b + nVar3;};
		System.out.println(lambdaInterface.lambdaExpression(nVar1, nVar2));		// 9
		
		lambdaInterface = (a, b) -> {return a * b * nVar3;};
		System.out.println(lambdaInterface.lambdaExpression(nVar1, nVar2));		// 24
		
		//Error : Local variable nVar3 defined in an enclosing scope must be final or effectively final
		//nVar3 = 1; 
	}

}

람다식에서 nVar3(지역변수)의 값을 사용하도록 하였다.

nVar3 값을 수정하게 되면 "Local variable nVar3 defined in an enclosing scope must be final or effectively final" 메세지가 출력된다.

final은 알겠는데 effectively final은 무엇을 뜻하는 것일까?

 

effectively final

초기화된 이후 값이 한 번도 변경되지 않았다면 effectively final이라고 할 수 있다. effectively final 변수는 final 키워드가 붙어있지 않았지만 final 키워드를 붙인 것과 동일하게 컴파일러에서 처리한다. ‘의미상 final 하다.’ 고 이해해도 괜찮을 것 같다.

 


람다식 장점

  • 코드를 간결하게 만들 수 있다.
  • 식에 개발자의 의도가 명확히 드러나 가독성이 높아진다.
  • 함수를 만드는 과정 없이 한 번에 처리할 수 있어 생산성이 높아진다.

람다식 단점

  • 디버깅이 어렵다.
  • 람다를 알고 있는 사람이라면 가독성이 장점이 되겠지만, 람다에 대해 잘 모르는 사람에게는 가독성이 나쁜 코드가 된다.
반응형

관련글 더보기

댓글 영역

>