activity/인프런 워밍업 클럽

[인프런 워밍업 클럽 0기] 세 번째 과제 - 익명클래스와 람다식

dani0312 2024. 2. 21. 16:31

강의

기본적인 데이터베이스 사용법

Database의 필요성에 대해 학습하고 MySQL에서 데이터베이스를 만들어 여러가지 쿼리를 작성해보았다. 메모리에 저장하여 데이터가 날아가던 것을 JdbcTemplate을 이용하여 데이터데이스에 저장하는 실습을 하였다. 


과제

우리는 JdbcTemplate을 사용하는 과정에서 익명 클래스와 람다식이라는 자바 문법을 사용했습니다. 익명 클래스는 자바의 초창기부터 있던 기능이고, 람다식은 자바 8에서 등장한 기능입니다. 다음 키워드를 사용해 몇 가지 블로그 글을 찾아보세요! 아래 질문을 생각하며 공부해보면 좋습니다! 😊

 

[키워드]

익명 클래스 / 람다 / 함수형 프로그래밍 / @FunctionalInterface / 스트림 API / 메소드 레퍼런스

 

[질문]

  • 자바의 람다식은 왜 등장했을까?
  • 람다식과 익명 클래스는 어떤 관계가 있을까? - 람다식의 문법은 어떻게 될까?

익명 클래스와 람다 표현식은 자바에서 코드를 간결히 사용하고 객체 지향 프로그래밍에서 유용하게 활용할 수 있는 기능이다. 이 두 가지에 대해 알아보고 둘의 관계에 대해 알아보고자 한다.

 

📌람다식

◾자바의 람다식은 왜 등장했을까?

 

람다식(Lambda Expression)이란

람다 표현식은 자바8부터 도입되었으며, 함수형 프로그래밍을 지원하기 위한 것이다. 주로 함수형 인터페이스를 구현하기 위해 사용된다. 

 

람다식이란 함수를 하나의 식으로 표현한 것이다. 함수를 람다식으로 표현하면 메소드의 이름이 필요 없기 때문에, 람다식은 익명 함수의 한 종류라고 볼 수 있다.

 

💡익명 함수란
익명함수(Anonymous function)는 이름이 없는 함수를 의미한다. 일반적으로는 함수 이름으로 호출하여 함수를 사용하지만, 익명 함수는 이름 없이 정의되어 사용되는 함수이다. 
> 장점: 익명함수는 함수를 일시적으로 필요한 곳에서 정의하고 사용할 때 유용하다.

 

 

람다식 등장 배경(사용 이유)

1. 코드의 간결성과 가독성 향상:

코드를 더 간결히 작성할 수 있다. 특히 간단한 연산이나 콜백 함수를 다룰 시 불필요한 부분을 제거하고 코드의 의도를 더 명확하게 전달할 수 있다.

2. 함수형 프로그래밍 지원: 

람다식은 함수형 프로그래밍을 지원하는 중요한 도구 중 하나이다. 함수형 프로그래밍은 함수를 일급 객체로 취급하고, 함수 조합을위해 코드를 간결하고 유연하게 작성하는 패러다임을 의미한다.

→ 람다식은 이러한 함수형 프로그래밍 개념을 자바에 도입하여 함수의 스타일의 코드 작성을 용이하게 만들었다.

3. 컬렉션 처리 간소화:   

람다식은 컬렉션 데이터를 다루는데 간소화된 구문을 제공한다. Java8 부터 도입된 스트림(Stream) API는 람다식을 기반으로 하며, 이를 통해 데이터를 병렬로 처리하고 다양한 연산을 할 수 있다.

→ 이는 코드를 간결하게 만들고 성능을 향상시킬 수 있다.

4. 인터페이스 기능 강화:

람다식은 함수의 인터페이스를 효과적으로 지원한다. 함수형 인터페이스는하나의 추상 메소드만을 가지는 인터페이스를 말하며, 람다식은 이러한 함수형 인터페이스의 인스턴스를 생성하기 위한 간단한 문법을 제공한다. 

이로써 익명 클래스를 사용하지 않고도 간단한 함수를 구현할 수 있게 되었다.

 

 

람다식의 단점

1. 재사용 불가: 람다를 사용하면서 만든 익명함수는 재사용이 불가능하다.

2. 디버깅 어려움: 이름이 없어 함수 호출 스택에서 식별이 어렵다.

3. 중복 코드 생성 가능성: 람다를 남발하면 비슷한 함수가 중복 생성되어 코드가 길어지고 지저분해진다.

4. 성능차 발생 가능성: 이론상 람다식이 반복문을 사용해 모든 컬렉션(예:리스트)의 원소를 순회할 시 일반적인 함수보다 약간 느릴 수 있다.

 

람다식은 이렇듯 단점도 존재한다. 상황에 따라 필요성에 맞도록 쓰는 것이 좋다고 한다.

 

 

◾람다식과 익명 클래스는 어떤 관계가 있을까?

 

익명클래스(Lambda Expression)란

이름이 없는 클래스로, 객체 사용시에 클래스의 선언과 객체 생성이 동시에 이루어진다. 

 

위에 언급한 익명 함수와 마찬가지로 일회성으로 사용하기 위한 목적이므로 이름이 없는 것이다. 프로그램에서 한 번만 사용되고 버려지는 객체이다. 이는 재사용이 되지 않는다는 것이며, 이 뜻은 확장성은 그리 좋지 못하다고 볼 수 있다.

 

익명클래스를 사용하기 위해서는 추상클래스나 인터페이스가 필요하다. 인터페이스는 객체를 생성할 수 없으므로 인터페이스의 필드를 사용하기 위해서는 따로 인터페이스를 구현받아 재정의하여 사용하도록 인터페이스를 구현받을 클래스가 필요하다. 

 

익명클래스를 사용하는 이유

1. 프로그램 내 일시적으로 한번만 사용되어야 하는 객체일 경우

2. 재사용성이 없고, 확장성을 활용하는 것이 유지보수에서 더 불리할 때

 

익명클래스의 의미와 사용 이유를 알아보니 람다식과 유사하다는 것을 알 수 있다. 이 둘은 어떤 관계가 있을까?

 

 

람다식과 익명 클래스의 관계

 

위에 살펴보았던 람다식의 4번째 장점을 다시 살펴보면 아래와 같다.

4. 인터페이스 기능 강화:
람다식은 함수의 인터페이스를 효과적으로 지원한다. 함수형 인터페이스는 하나의 추상 메소드만을 가지는 인터페이스를 말하며, 람다식은 이러한 함수형 인터페이스의 인스턴스를 생성하기 위한 간단한 문법을 제공한다. 
→ 이로써 익명 클래스를 사용하지 않고도 간단한 함수를 구현할 수 있게 되었다

 

람다식은 익명클래스를 만드는 과정을 더 생략할 수 있는 문법이다. 코드도 당연히 더 간결해진다. 

단, 람다식이 적용될 때는 추상클래스 혹은 인터페이스 안에 정의된 추상메서드가 딱 하나인 경우에만 가능하다!

함수형 인터페이스가 무엇인지 와닿지 않는다면 아래를 참고하자.

 

💡함수형 인터페이스란?
Functional Interface는 일반적으로 ‘구현해야 할 추상 메소드가 하나만 정의된 인터페이스’를 가리킵니다.

 구현해야 할 메소드가 '1개'이므로 Functional Interface이다.(함수형 인터페이스⭕)
        @FunctionalInterface
        public interface Calc {
            public int sum(int num1, int num2);
        }​

 

 구현해야 할 메소드가 '2개'이므로 Functional Interface가 아니다.(함수형 인터페이스❌)
	    @FunctionalInterface //error!
            public interface Calc {
            public int sum(int num1, int num2);
            public int minus(int num1, int num2);
        }​


 

 

익명클래스  vs   람다식

🔻인터페이스

interface Note {
    void draw();
}

 

🔻익명클래스

public class AnonymousClassAndLambdaEx {
    public static void main(String[] args) {
        // 익명 클래스를 사용하여 MyFunctionalInterface의 인스턴스 생성
        Note anonymousClassInstance = new Note() {
            @Override
            public void draw() {
                System.out.println("토끼를 그린다.");
            }
        };
        // 익명 클래스의 메소드 호출
        anonymousClassInstance.draw();
    }
}

 

🔻람다식

public class AnonymousClassAndLambdaEx {
    public static void main(String[] args) {
        // 람다식을 사용하여 MyFunctionalInterface의 인스턴스 생성
        Note lambdaInstance = () -> System.out.println("토끼를 그린다.");

        // 람다식의 메소드 호출
        lambdaInstance.draw();
    }
}

 

람다식을 사용하니 코드가 훨씬 간결해지는 것을 볼 수 있다. 익명클래스에서는 인터페이스의 추상메서드를 오버라이딩 하여 사용한다. 람다식은 익명클래스를 구현해주는 인터페이스의 추상메서드가 단 한개일때 코드를 줄여주므로 람다식을 통해 Note인터페이스의 추상메서드 drow()를 오버라이딩 해준 것과 같다. 

 

이렇듯 람다식은 익명클래스를 만들 시 구현하려는 부모의 오브젝트(`Note`)의 추상메서드(`draw()`)가 하나라면 코드를 더 생략하여 사용하는 문법이다. 

 


◾람다식 문법

람다식 기본 문법

람다식의 기본 문법에 대해 알아보자

(parameters) -> expression

 

 

위의 요소를 하나씩 살펴보자

1. 파라미터(Parameters)

- 괄호 안에 전달받을 매개변수를 나열한다.

- 매개변수가 없을 시 빈 괄호를 사용한다. 

- 여러 개의 매개변수가 있을 경우 쉼표로 구분한다.

 

2.화살표(->)

- 화살표는 매개변수와 람다 본문을 구분한다.

 

3. 람다 본문(Expression or Block) (함수 몸체)

- 람다 표현식의 본문은 중괄호 `{}`안에 위치하며, 식(expression) 또는 블록(block)으로 표현할 수 있다. 

- 식으로 표현할 경우, 별도의 `return`문이 필요 없다.

- 블록으로 표현할 경우, 명시적으로 `return`문을 사용해야 한다.

 

 

 

다양한 람다식

1. 파라미터가 없는 경우

() -> System.out.println("Hello, Lambda!");

 

2. 파라미터가 한 개인 경우

(name) -> System.out.println("Hello, " + name);

 

3. 파라미터가 여러 개인 경우

(x, y) -> {
    int result = x + y;
    System.out.println("Result: " + result);
    return result;
};

 

4. 반환값이 있는 경우

(x, y) -> x + y

 

5. 함수형 인터페이스 구현 예제

        // 1. 함수형 인터페이스 선언
        @FunctionalInterface
        interface Math{
            public int Calc(int first, int second);
        }

        // 2. 추상 메서드 구현 및 함수형 인터페이스 사용
       	Math plusLambda = (first,second) -> first + second;
        System.out.println(plusLambda.Calc(4,2)); // 결과:6
        
        Math minusLambda = (first,second) -> first - second;
        System.out.println(minusLambda.Calc(4, 2)); // 결과:2

 

 

 

정상유형과 잘못된 유형 살펴보기

정상유형

//정상적인 유형
() -> {}
() -> 1
() -> { return 1; }
(int x) -> x+1
(x) -> x+1
 x -> x+1
(int x) -> { return x+1; }
 x -> { return x+1; }
(int x, int y) -> x+y
(x, y) -> x+y
(x, y) -> { return x+y; }
(String lam) -> lam.length()
lam -> lam.length()
(Thread lamT) -> { lamT.start(); }
lamT -> { lamT.start(); }

 

잘못된 유형 

//잘못된 유형 선언된 type과 선언되지 않은 type을 같이 사용 할 수 없다.
(x, int y) -> x+y
(x, final y) -> x+y

 

 

 

잘못된 내용이 있다면 댓글로 알려주시면 감사하겠습니다❤️

좋은 하루 되세요😊 


Reference

자바와 스프링 부트로 생애 최초 서버 만들기 [서버 개발 올인원 패키지] / 최태현 / 인프런 강의

https://limkydev.tistory.com/226

https://mangkyu.tistory.com/113 람다식 등장 이유

https://chat.openai.com 람다식 등장 배경, 람다식 예제

https://junghn.tistory.com/entry/JAVA-%EB%9E%8C%EB%8B%A4%EC%8B%9DLambda-Expressions%EC%9D%B4%EB%9E%80-%EC%82%AC%EC%9A%A9%EB%B0%A9%EB%B2%95-%EC%9E%A5%EB%8B%A8%EC%A0%90 람다식 장단점

https://kadosholy.tistory.com/103 익명클래스란

https://u-it.tistory.com/33 익명클래스와 람다식

https://medium.com/@khj93/java-%EB%9E%8C%EB%8B%A4%EC%8B%9D-lambda-%EC%9D%98-%EA%B0%9C%EB%85%90-%EB%B0%8F-%EC%82%AC%EC%9A%A9%EB%B2%95-34ee86f6c1d7 람다식 사용법