상세 컨텐츠

본문 제목

[Java] 2. JDK 8에 추가된 주요 문법(Lambda)

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

by Guroo 2023. 8. 3. 18:01

본문

 

[Java] 1. Java SE Version 변화 소개

 

[Java] 1. Java SE Version 변화 소개

자바언어는 1996년 JDK 1.0을 출시한 이후 수많은 버전으로 업데이트되어 현재에 이르렀다. 아래의 표는 JDK 7 버전 이후 각 버전별로 Java SE Support Roadmap을 정리한 Oracle 문서이다. 아래 표에서 주의

sesoc.tistory.com

 

1. JDK 8에서 추가된 주요 문법은  

  1. Lambda Expression
  2. Interface의 default Method
  3. Stream API
  4. Optional
  5. LocalDate, LocalTime, LocalDateTime

 

등이 있다.

 

2. 일급 함수(First Class Citizen)의 개념

Java 버전 8에서 추가된 문법인 람다에 대해 배우기 이전에 먼저 일급함수에 대해 정리해보자.

 

일급함수는 함수형 언어에서 주로 사용되는 개념으로써, 자바스크립트나 코틀린과 같은 언어에서 함수는 자바의 메소드와는 다르게 함수가 하나의 값으로 취급된다.

 

C언어나 Java언어에서 전통적인 의미의 함수(혹은 메소드)는 함수를 정의하고, 정의된 함수를 호출해서 그 기능을 사용하는 개념이다.

 

그런데 함수를 값으로 처리하게 되면  함수를 변수에 대입하거나 함수를 다른 함수의 전달인자로 전달하고, 함수를 반환하는 등의 동작을 할 수 있는데 이런 기능을 충족하는 함수를 일급함수라고 한다.

 

일급함수는

  • 함수를 변수에 대입할 수 있다
  • 함수를 다른 함수로 전달할 수 있다.
  • 함수 자체가 리턴된다.

 

일급함수의 개념을 자바 스크립트의 코드를 예로 들어보자. 아래의 코드는 add()라는 함수가 정의되어 있고 이 함수를 호출하여 그 결과를 출력하는 일반적인 방식의 함수 사용방법이다.

// 1) 함수 정의
function add(a, b) {
  return a + b;
}

// 2) 함수 호출
let result = add(10, 15);
console.log('더하기 결과:', result);

 

** 변수에 대입되는 함수

아래의 코드는 이름이 없는 익명의 함수를 정의하고 이 함수를 변수 add에 대입하여 사용하는 것이다.

함수가 변수에 대입되면 이 변수명을 이용해 함수를 호출할 수 있다.

// 함수를 변수에 대입
let add = function(a, b) {
  return a + b;

}

// 변수명을 이용해 함수 호출
let result = add(10, 15);

console.log('더하기 결과:', result);

 

** 함수를 반환하는 함수

이번에는 함수를 반환하는 함수의 예를 보자.


아래 hello()라는 함수의 반환값은 익명함수이다. 이 익명함수를 사용하기 위해서는 hello() 함수가 반환하는 함수를 변수에 담은 후 그 변수를 이용해 리턴되는 함수를 사용할 수 있다.

// 1) 함수를 반환

function hello(name) {
  return function () {
    console.log(`안녕하세요? ${name}님`);
  }
}

let func = hello('전우치');
func();             // 안녕하세요? 전우치님
hello('손오공')();  // 안녕하세요? 손오공님

 

 ** 함수를 다른 함수의 전달인자로 전달

이번에는 함수를 다른 함수의 전달인자로 전달하는 예이다.

자바스크립트에서 많이 사용하는 setTimeout() 함수는 두 개의 데이터를 전달받는데, 첫 번째 전달되는 데이터가 익명함수이고, 두번째로 전달되는 값은 익명함수를 언제 호출할지 알려주는 밀리세컨의 값이다.

 

아래의 코드는 1000 밀리세컨. 즉, 1초가 지나면 첫 번째 전달인자인 익명함수를 호출하게 되는데, 이 익명함수의 내부에서는 현재 시스템 시간을 읽어 콘솔창에 출력한다.

 

여기에서 중요한 것은 setTimeout() 함수의 첫 번째 전달인자가 함수라는 것이다.

setTimeout(function () {
  let today = new Date();
  let now = `${today.getHours()} : ${today.getMinutes()} : ${today.getSeconds()}`;
  console.log(now);
}, 1000);

자바스크립트의 함수는 일급함수가 갖춰야(?) 하는 조건을 다 충족한다.

 

자바의 람다 표현식을 이해하기 위해서는 일급함수의 뜻을 알아 둘 필요가 있다.

 

 

3. 자바 람다 표현식(Lambda Expression)

자바에서 람다 표현식은 메소드를 하나의 식으로 표현한 것을 말하며 메소드에 이름이 없으므로 익명함수(Anonymous function)이라고 부른다.

람다식으로 작성되는 메소드는 1회만 사용되고, 메소드 내 문장이 짧은 경우 유용하다.

 

자바는 객체지향 언어이므로 모든 메소드는 클래스나 인터페이스 내에 존재해야 한다.

 

즉, 하나의 메소드를 작성하기 위해서는 메소드를 포함하는 클래스나 인터페이스를 생성하고 그 객체를 생성해야 해당 메소드를 사용할 수 있다. 이에 비해 람다식은 클래스를 생성하지 않아도 사용할 수 있도록 한다.

자바의 람다식은 람다식을 정의하는 시점에는 이름이 필요 없으므로 익명 클래스라고 할 수 있다.

 

먼저, 아래의 두 코드를 살펴보자. MyCalculator라는 이름의 인터페이스에는 두 개의 정수 값을 전달받아 두 값의 비교한 결과를 반환하기 위해 선언된 메소드 compare() 가 있다.

 

전달된 두 값이 같으면 0, a변수로 전달된 값이 크면 양수, b변수로 전달된 값이 뒤의 값이 크면 음수를 반환하도록 Override 한다고 하자.

 

이 메소드를 사용하려면 객체를 생성한 후 생성된 객체를 이용해서 compare() 메소드를 사용해야 한다. 그러나 인터페이스는 객체를 생성할 수 없으므로 이를 위해서는 아래와 같이 생성과 동시에 Override를 해야 하는 번거로운 작업을 거쳐야 하는데, 이를 간단히 람다식으로 변환할 수 있다.

 

3-1. 이전 방식

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

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

        MyCalculator calc = new MyCalculator() {
            @Override
            public int compare(int a, int b) {
                return a - b;
            }
        };
 
        int result = calc.compare(a,  b);
        System.out.printf("%d가(이) %d보다 %S%n", a, b, (result < 0) ? "작다": "크다");
    }
}

 

3-2. 람다식을 이용한 변환

위에서 작성한 코드를 람다식으로 변환하면 아래와 같이 사용될 수 있으며 결과는 동일하다.

자바에서 람다식을 정의할 때 주의할 점은 반환되는 데이터의 값이 정수라고 해서 대입 연산자 좌측의 변수를 int로 선언해서는 안 된다는 점이다.

 

재정의하려는 메소드는 MyCalculator 인터페이스 내에 존재하는 compare() 메소드이므로 반환타입은 그 메소드가 속한 인터페이스 변수이다.

그러므로 자바에서 작성된 람다식은 엄밀하게 말하면 식이 아니라 객체라고 보아야 하므로 람다객체라는 표현이 더 적절하다.

 

이렇게 람다객체로 반환된 값을 사용하는 시점에서는  실제 메소드명인 compare()를 호출해야 한다.

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

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

             MyCalculator calc = (x, y) -> x - y; // 람다객체 정의
             // int calc = (x, y) -> x – y;       // 틀린 표현

             int result = calc.compare(a,  b);     // 사용
             System.out.printf("%d가(이) %d보다 %S%n", a, b, (result < 0) ? "작다": "크다");
       }
}

 

[참고] 자바스크립트 화살표 함수의 예

let x = 15, y = 10;
let result = (x, y) => x - y;  // result변수는 람다함수

console.log(x, '는(은)', y, '보다', result(x, y) > 0 ? '크다' : '작다');

 

참고적으로 자바스크립트에도 람다식과 유사한 화살표함수가 있는데, 자바스크립트에서는 화살표함수가 람다함수라고 할 수 있다.

 


 

이전글: 1. Java SE Version 변화 소개

 

다음글: 3. Lambda 기본문법

'프로그래밍 언어 > Java(자바)' 카테고리의 다른 글

[Java] 3. Lambda 사용을 위한 문법  (0) 2023.08.04
[Java] 1. Java SE Version 변화 소개  (0) 2023.08.03
숫자 야구 게임  (0) 2023.06.29

관련글 더보기

댓글 영역