상세 컨텐츠

본문 제목

[Java] 3. Lambda 사용을 위한 문법

프로그래밍 언어/Java(자바)

by Guroo 2023. 8. 4. 09:35

본문

 

1. 함수형 인터페이스 정의

앞에서도 언급했듯이 자바는 객체지향형 언어이기 때문에 함수를 일급함수로 다루려면 인터페이스가 제공되어야 하는데 람다식을 다루기 위해 함수형 인터페이스는 단 하나의 추상 메서드만 선언된 함수형 인터페이스여야 한다.

 

즉, 함수형 인터페이스는 여러 개의 추상메소드를 가질 수 없다.

 

생성된 인터페이스가 함수형 인터페이스임을 명확히 하기 위해 인터페이스 상단에 @FunctionalInterface 애노테이션을 붙인다.

인터페이스 상단에 @FunctionalInterface 애노테이션을 반드시 붙여야 하는 것은 아니다.

그러나, 인터페이스가 람다식을 작성할 목적으로 만들어졌다면 그 의미를 명확히 하기 위해 애노테이션을 붙이는 것이 좋다.

 

1-1. 함수형 인터페이스 선언

인터페이스 상단에 @FunctionalInterface 애노테이션을 선언한 후 하나의 추상 메소드를 선언한다.

@FunctionalInterface
interface MyCalculator {
       public int compare(int a, int b);
}

 

위에서 언급했 듯이 함수형 인터페이스에 둘 이상의 메소드가 선언될 경우는 오류이다. 

 

아래의 @FunctionalInterface 를 머리에 이고 있는 MyCalculator 인터페이스에 even() 메소드를 선언하면

"Invalid '@FunctionalInterface' annotation; MyCalculator is not a functional interface"

라는 오류가 발생한다.

@FunctionalInterface
interface MyCalculator {
       public int compare(int a, int b);
       public boolean even(int a);           // 오류
}

 

1-2. default 메소드

@FunctionalInterface로 선언된 인터페이스에 둘 이상의 메소드를 선언하고자 하면 추가된 메소드는 “default” 키워드를 붙이고 메소드의 body 부분을 정의해야 한다.

@FunctionalInterface
interface MyCalculator {
       public int compare(int a, int b);
       public default int add(int a, int b) {
             return a + b;
       }
}

public class TestLambda03 {
       public static void main(String[] args) {
             int a = 15, b = 10;

             MyCalculator calc = (x, y) -> x - y; // 람다객체 정의
             int result = calc.compare(a,  b);
             System.out.printf("%d가(이) %d보다 %S%n", a, b, (result < 0) ? "작다": "크다");

             result = calc.add(a,  b);
             System.out.printf("%d + %d = %d%n", a, b, result);
       }
}

 

 

2. 람다식 정의 순서

2-1. 예-1

MyCalculator 인터페이스 내의 compare() 메소드를 람다식으로 정의해보자

@FunctionalInterface
interface MyCalculator {
   public int compare(int a, int b);
}

 

MyCalculator 인터페이스의 compare () 메소드는 두개의 정수형 값을 전달받아 비교하는 작업을 거친 후 그 결과를 다시 정수로 반환하는 메소드이다.

 

추상 메소드인 compare() 메소드를 정의하는 람다식은 아래의 순서로 만들  수 있다.

 ①   메소드의 접근지정자 public과 메소드 명 compare를 제거
      (int a, int b) { return a – b; }

 

②   매개변수의 타입 제거, 매개변수가 하나일 때는 소괄호도 생략 가능
      (a, b) { return a – b; }

 

③   매개변수를 위한 닫히는 소괄호와 메소드 정의를 위해 열리는 중괄호 사이에 -> 삽입
      (a, b) -> { return a – b; }

 

④   메소드 정의부의 중괄호와 return문 제거
      (a, b) -> a – b;

 

⑤   정의된 메소드의 반환값을 이 메소드가 정의된 인터페이스 타입으로  받는다.
      MyCalculator calc = (a, b) -> a – b;

 

⑥   메소드명 이용하여 람다식 사용
      int result = calc.compare(10, 15)

 

2-2. 예-2 : 매개변수가 1개

위의 공식(?)을 사용하여 매개 변수가 1개이고, boolean을 반환하는 람다식을 정의하고 사용하면 아래의 코드처럼 사용할 수 있다.

 

@FunctionalInterface
interface MyCalculator2 {
       public boolean isEven(int a);
}

 // 매개 변수가 1개일 경우 () 생략 가능

MyCalculator2 calc2 = x -> x % 2 == 0 ? true : false;

boolean bool = calc2.isEven(a);
System.out.printf("%d는 %s다%n", a, bool ? "짝수" : "홀수");

 

 

2-3. 예-3 : 매개변수 반환값 모두 없는 경우

 

이번에는 매개 변수도 없고 반환값도 없는 람다식을 작성하는 코드를 살펴보자

@FunctionalInterface
interface MyCalculator3 {
       public void output();
}


// 3) 매개변수가 없는 경우 () 생략 불가
//    return이 없으므로 메소드 내부에서 실행할 문장 작성
MyCalculator3 calc3 = () -> System.out.println("매개변수도 반환값도 없음");
calc3.output();

 

2-4. 예-4 : 메소드 내부 실행문이 한 줄 이상인 경우

람다식으로 정의될 메소드 내부의 코드가 아래와 같이 길 경우에는 {}도 생략할 수 없고, return 도 생략할 수 없다.

 

@FunctionalInterface
interface MyCalculator4 {
       public double power(double a, int b);
}

// 함수의 정의부가 여러 줄일 때는 {}와 return 생략 불가
MyCalculator4 calc4 = (x, y) -> {
       double r = 1;
       for(int i=0; i<y; ++i) r *= x;
       return r;
};

double c = 1.2;
System.out.printf("%.2f의 %d 거듭제곱 값은 %.5f다.%n", c, b, calc4.power(c, b));

 

 여기까지 자바에서 람다식을 작성하는 기본적인 문법을 살펴보았다.

다음에는 이미 정의 되어있는 함수형 인터페이스 내의 추상메소드를 람다식으로 정의하는 방법을 보도록 하자.


이전글: 2. JDK 8에 추가된 주요 문법(Lambda)

 

다음글: 4. java.util.function 패키지에 정의된 Lambda

 

 

관련글 더보기

댓글 영역