람다식(Lambda expression) 이란??

Jaeho Kim·2022년 4월 22일
2

자바의정석

목록 보기
6/7

✏️ 람다식이란??

메서드를 하나의 "식(expression)"으로 표현한 것
람다식으로 표현하면 메서드의 이름과 반환값이 없어지므로, "익명함수" 라고도 한다.

  • 메서드를 하나의 "식(expression)"으로 표현한 것
  • 함수명을 선언하고 사용하는 것이 아닌 식별자 없이 실행가능한 함수입니다.
  • 절차형 프로그래밍, 객체지향 프로그래밍과는 사뭇 다르게 함수의 구현과 호출만으로 프로그램을 만드는 방식인 함수형 프로그래밍에서 자주 사용 됩니다.
  • 자바8부터 도입이 되었으며, 람다식을 익명함수로 만드는 것인데 익명함수는 일급객체 특징을 가지고 있습니다.
  • 람다식 사용법 예시 ==>> ( 매개변수 , ... ) - > { 실행문 ... }

일급객체란?

  • 일급 객체(First Class citizen) :
    일반적으로 다른 객체들에 적용 가능한 연산을 모두 지원하는 객체.
    함수를 값으로 사용 할 수도 있으며 파라미터로 전달 및 변수에 대입 하기와 같은 연산들이 가능.

  • 일급 객체(First-Class Object) 조건
    변수나 데이터 구조 안에 담을 수 있음.
    파라미터로 전달 할 수 있음.
    반환값으로 사용할 수 있음.
    할당에 사용된 이름과 무관하게 고유한 구별이 가능.
    함수형 프로그래밍에서 함수는 1급 객체로 취급받기 때문에 위의 예제에서 본 것 처럼 함수를 파라미터로 넘기는 등의 작업이 가능한 것이다. 또한 우리가 일반적으로 알고 개발했던 함수들은 함수형 프로그래밍에서 정의하는 순수 함수들과는 다르다는 것을 인지해야 함.

// 람다식 변환 예시
int[] arr = new int[5];									// 기본
Arrays.setAll(arr, (i) -> (int) (Math.random()*5)+1);	// 람다식
							↓
							↓
                            ↓
int  method() {											// 람다식을 메서드로 표현
	return (int) (Math.random()*5) + 1;
}

람다식을 사용해서 해소되는 불편한 점

  • 메서드를 호출하기 위한 불필요한 class, 객체 생성의 과정 불필요.
  • 람다식 자체로 메서드의 매개변수로 전달되어지는 것이 가능 => 결과로 반환 가능
    --> 메서드를 변수처럼 다루는 것이 가능해짐

✏️ 람다식 작성하기

람다식은 '익명 함수'답게 메서드에서 이름과 반환타입을 제거하고
매개변수 선언부와 몸통{} 사이에 '->'를 추가한다.

(int a, int b) -> { return a > b ? a : b; }		// 반환타입과 이름 제거
(int a, int b) -> a > b ? a : b 				// return을 식으로 대신, 식이므로 ; 생략
(a, b) -> a > b ? a : b							// 추론이 가능한 경우 타입 생략가능
// 단, 일괄 생략해야함. (일부만 불가능)
// 매개변수의 타입이 있는경우, 괄호 생략 불가능
(a, b) -> a > b ? a : b							// 추론이 가능한 경우 타입 생략가능
(String name, int i) -> System.out.println(name+"="+i)	
// 괄호안의 문장이 하나일 때는 괄호 생략 가능, 이때 ; 붙히면 안된다.
// 단, 괄호안의 문장이 return 문일 경우 괄호 생략 불가

✏️ 함수형 인터페이스(Functional Interface)

자바에서 모든 메서드는 클래스 내에 포함되어야 하는데, 람다식은 어떤 클래스에 포함되는 것일까?
람다식은 익명 클래스의 객체와 동등하다

// MyFunction 인터페이스가 있을때,
interface MyFunction {
	public abstract int max(int a, int b);
}
// 이 인터페이스를 구현한 익명 클래스의 객체는 다음과 같이 생성할 수 있다.
MyFunction f = new MyFunction() {
					public int max(int a, int b){
                    	return a > b ? a : b;
                    }
			};
// 익명 객체를 람다식으로 대체
// MyFunction f = (int a, int b) ->a > b ? a : b;
// 익명 객체의 메서드를 호출
int big = f.max(5, 3);	
  • 구현이 가능한 이유?
    매개변수의 타입과 개수 그리고 반환값이 일치했기 때문에

람다식을 다루기 위한 인터페이스를 '함수형 인터페이스(functional interface)'라고 부르기로 했다.
단, 함수형 인터페이스에는 오직 하나의 추상 메서드만 정의되어 있어야 한다는 제약이 있다.
하지만 static메서드와 default메서드의 개수에는 제약이 없다.

함수형 인터페이스 타입의 매개변수와 반환타입

  • 람다식을 매개변수로 지정 가능하며, 반환타입으로 이용할 수 있다.

람다식의 타입과 형변환

  • 람다식은 익명 객체이므로 타입이 없고, 함수형 인터페이스로 람다식을 참조할 수 있는 것일 뿐 람다식의 타입이 함수형 인터페이스의 타입과 일치하는 것은 아니다.

  • 실제로 타입이 없는것은 아니고, 타입은 있지만 컴파일러가 임의로 이름을 정하기 떄문에 알 수 없는 것이다.

  • 예제14-2 실행결과 확인
    LambdaEx2$$Lambda$1/123213213@8c4f57

외부 변수를 참조하는 람다식

  • 예제14-3
@FunctionalInterface
interface MyFunction{
	void run();	// public abstract void run();
}

class LambdaEx1 {
	static void execute(MyFunction f) {	// 매개변수의 타입이 MyFunction인 메서드
    	f.run();
    }
		
    static MyFunction getMyFunction() {	// 반환 타입이 MyFunction인 메서드
    	MyFunction f = () -> System.out.println("f3.run()");
    	return f;
    }
    
    public static void main(String[] args){
    	// 람다식으로 MyFunction의 run()을 구현
        MyFunction f1 = ()-> System.out.println("f1.run()");
    
    	MyFunction f2 = new MyFunction() {	// 익명클래스로 run()을 구현
        	public void run() {	// public을 반드시 붙여야 함
            	System.out.println("f2.run()");
            }
    	};
        
        MyFunction f3 = getMyFunction();
        
        f1.run();
        f2.run();
        f3.run();
        
        execute(f1);
        execute( ()-> System.out.println("run()") );
    }
}

람다식 내에서 참조하는 지역변수는 final이 붙지 않았어도 상수로 간주된다.
외부 지역변수와 같은 이름의 람다식 매개변수는 허용되지 않는다.

profile
Hello, World!

0개의 댓글