[java] Lambda

happiyoung_·2024년 8월 23일

java

목록 보기
7/9

Intro

자바는 원래 객체지향언어인데 빅데이터의 등장으로 처리가 빠른 함수형 언어 기능을 추가하면서 함수 (메서드)를 간단한 식(expression)으로 표현하는 방법이 등장하였다.

Lambda Expression

함수(메서드)를 간단한 '식(Expression)' 으로 표현하는 방법

int max (int a, int b) {
	return a > b ? a: b;
}

위의 함수를 아래와 같이 표현할 수 있다.

(a, b) -> a > b ? a : b

람다식을 만드는 방법

  1. 반환형과 함수이름을 지운다. (익명함수로 만들기)
  2. 함수의 매개변수와 바디 사이에 -> 를 넣는다.
  3. 반환값이 있는 경우, 식이나 값만 적고 return 문 생략 가능 (끝에 ';' 안 붙임)
  4. 매개변수의 타입이 추론 가능하면 생략가능 (대부분의 경우 생략가능)
    (int a, int b)(a, b) 가 된다.

람다식 만들 때 주의사항

  1. 매개변수가 하나라면 괄호 생략가능 (타입이 없는 경우)
  2. 블록 안의 문장이 하나뿐 일 때, 괄호 {} 생략 가능 (끝에 ';' 안 붙임)

(참고) 함수와 메서드의 차이

  • 근본적으로는 동일하나 함수는 일반적 용어, 메서드는 객체 지향 개념 용어이다.
  • 함수는 클래스에 독립적이며 메서드는 클래스에 종속적이다.

람다식 만들기 예제

(1번)

int max(int a, int b) {
	return a > b ? a : b;
}

(a, b) -> a > b ? a : b

(2번)

int printVar(String name, int i) {
	System.out.println(name+"="+i);
}

(name, i) -> System.out.println(name+"="+i)

(3번)

int roll() {
	return (int) (Math.random() * 6);
}

() -> (int) (Math.random() * 6)

익명 객체

자바에서 람다식은 익명 함수가 아니라 익명 객체이다.
(a, b) -> a > b ? a : b 은 익명클래스의 객체로 변환이 가능하다.
객체라고 한다면 다음과 같은 표현이 가능할까?
Object obj = (a, b) -> a > b ? a : b;
익명객체니까 객체레퍼런스 변수에 담을 수 있는 것 아닌가?
담을 수 없다 -> 오류
다음과 같이 작성해고 사용해야한다.

new Object() {
	int max(int a, int b) {
    	return a > b ? a : b;
    }
}

그렇다면 람다식인 익명객체를 다루기위해서 참조변수가 필요한데 이 참조변수의 타입은 어떻게 될까?

Object obj = new Object() {
	int max(int a, int b) {
    	return a > b ? a : b;
    }
};

하지만 max라는 함수가 존재해도 쓸수없다는 문제가 있다.
함수형 인터페이스로 해결 가능하다.

함수형 인터페이스

단 하나의 추상 메서드만 선언된 인터페이스

@FunctionalInterface // 함수형 인터페이스 임을 알려주는 (추상메서드 하나만 존재하는지 검사해준다.)
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;
                    }
               };

익명 클래스로 클래스의 선언과 객체 생성을 동시에 하고 있다.
이 경우 다음과 같은 호출이 에러가 되지않는다.

int value = f.max(3,5); // OK. MyFunction에 max()가 있음

또한 함수형 인터페이스 타입의 참조변수로 람다식을 참조할 수 있다.

MyFunction f = (a, b) -> a > b ? a : b;
int value = f.max(3,5); // 실제로는 람다식 (익명 함수)이 호출됨

이렇게 간단하게 사용가능하다.

람다식과 함수형 인터페이스 예제

class lambda_FI {
	public static void main(String[] args) {
    	MyFunction2 f = new MyFunction2() {
        	public int max(int a, int b) { // 오버라이딩 - 접근제어자는 좁게 못바꾼다. 인터페이스에서 default로 선언됨
            	return a > b ? a : b;
            }
      	};
        
        int value = f.max(3,5); // 함수형 인터페이스
        System.out.println("value=" + value);
    }
}
@FunctionalInterface // 함수형 인터페이스는 단 하나의 추상 메서드만 가져야 함
interface MyFunction2 {
	int max(int a, int b);
}

람다식을 적용하면 다음과 같이 간결하게 바꿀 수 있다.

class lambda_FI {
	public static void main(String[] args) {
    // 람다식(익명객체)을 다루기 위한 참조변수의 타입은 함수형 인터페이스
    	MyFunction2 f = (a,b) -> a > b ? a : b; // 람다식 익명 객체
        
        int value = f.max(3,5); // 함수형 인터페이스
        System.out.println("value=" + value);
    }
}
@FunctionalInterface // 함수형 인터페이스는 단 하나의 추상 메서드만 가져야 함
interface MyFunction2 {
	int max(int a, int b);
}

단, 람다식을 사용할때는 매개변수의 타입과 갯수 반환 타입이 같아야 한다.
람다식 자체는 간결하게 표현하고자 함수의 이름을 없앴지만 호출해서 함수를 사용하려면 이름이 반드시 필요하다. 이름을 붙여주는 과정을 함수형 인터페이스로 구현하는 것이다. 그래서 우리는 max라는 이름을 가진 함수를 정의하지않았지만 그 이름을 쓸수있게 된다.

Outro

함수를 간결하게 표현하는 방식인 람다식의 개념에 대해 살펴보았다. 간결하게 표현하자는 간단한 목적아래에서 만들어진 것이지만, 함수 객체를 만든다는 면에서 굉장히 중요하고 유용한것같다.

profile
해삐한 다영의 컴퓨터와 친해지기 프로젝트 🥰

0개의 댓글