[인프런 워밍업 클럽 1기] BE 3일차 과제

[인프런 워밍업 클럽 1기] BE 3일차 과제

[인프런 워밍업 클럽 1기] BE 3일차 과제

본 게시글은 다음 강의 내용을 진행하고 있습니다.

자바와 스프링 부트로 생애 최초 서버 만들기, 누구나 쉽게 개발부터 배포까지! [서버 개발 올인원 패키지] - https://inf.run/XKQg

[키워드]

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

키워드를 참고해 찾아본 각 키워드의 정의와 특징을 간단하게 정리해보고 질문에 답변해보려고 한다.

 

익명 클래스

정의

이름이 없는 클래스로, 클래스의 정의와 동시에 객체를 생성할 수 있는 방법이다.

특징

  • 클래스 이름이 없어 특정한 위치에서 직접적으로 선언되며, 이와 동시에 객체가 인스턴스화 된다.

  • 주로 일회성으로, 재사용이 필요 없는 특정 상황이나 동작을 구현하는 데에 주로 사용된다.

  • 복잡한 클래스를 별도로 선언할 필요 없이 필요한 구현 부분만을 직접 작성할 수 있다.

  • 코드를 더욱 간결하고 읽게 쉽게 만들며, 불필요한 클래스 선언을 줄여준다.

 

람다

정의

코드 가독성을 위해 도입된 익명 클래스 객체를 더욱 더 간결하고 명확하게 표현할 수 있도록 하는 것이다.

특징

  • 함수의 이름과 반환값이 없어져 익명 함수의 한 종류로 취급한다.

  • 함수를 변수처럼 전달하거나 반환하는 데 사용된다.

  • 익명 함수를 사용하는 것보다 더 적은 코드로 동일한 내용을 구현할 수 있다.

 

함수형 프로그래밍

정의

프로그래밍 패러다임 중 하나로, 순수 함수를 기반으로 데이터 처리와 상태 변화를 최소화하는 방식의 프로그래밍 기법이다.

특징

  • 동일한 입력에 대해 항상 같은 결과를 반환하며, 외부 상태를 변경하지 않는 함수인 순수 함수를 사용한다.

  • 순수 함수를 사용하여 코드의 복잡성에 따른 부작용을 최소화하여 프로그램의 유지 보수와 테스트를 용이하게 하도록 한다.

 

@FunctionalInterface

정의

함수형 인터페이스를 선언할 때 사용하는 어노테이션이다.

특징

  • 함수형 인터페이스는 하나의 추상 메서드만을 가지고 있어야 한다.

  • 인터페이스에 어노테이션을 사용하면 해당 인터페이스가 함수형 인터페이스인지 검사한다.

  • 다음과 같은 형식으로 함수형 인터페이스를 선언한다.

@FunctionalInterface
interface MyFunction {
    void myMethod();
}

// 함수형 인터페이스의 구현
MyFunction func = () -> System.out.println("함수형 인터페이스의 메소드 구현");

 

스트림 API

정의

컬렉션, 배열 등의 저장 요소를 조작 및 가공, 변환하여 원하는 값으로 반환해주는 인터페이스이다.

특징

  • 원본 데이터를 조회하여 별도의 Stream 객체로 생성을 하기 때문에 배열의 정렬이나 필터링 작업을 하더라도 원본 데이터를 변경하지 않는다.

  • 이미 사용이 되어 닫히면 재사용이 불가능하며 새로운 Stream을 생성해주어야 한다.

  • Stream 내에서 내부적으로 반복문을 처리하기에 간결한 소스코드의 작성이 가능하다.

     

     

메소드 레퍼런스

정의

메소드를 직접 참조하여 람다 표현식을 더 간결하게 만들어주는 방법이다.

특징

  • 기존의 메서드 정의를 재활용해 람다와 같이 사용할 수 있다.

  • 메소드 레퍼런스의 종류

종류 : 정적 메서드 참조
람다 표현식 : (x) -> ClassName.method(x)
메서드 참조 : ClassName::method

종류 : 인스턴스 메서드 참조
람다 표현식 : (x) -> obj.method(x)
메서드 참조 : obj::method

종류 : 매개변수의 메서드 참조
람다 표현식 : (obj, x) -> obj.method(x)
메서드 참조 : ClassName::method

종류 : 생성자 참조
람다 표현식 : (x, y) -> new ClassName(x, y)
메서드 참조 : ClassName::new

 

[질문]

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

A. 궁극적으로 람다식이 등장한 이유는 불필요한 코드를 줄이고, 가독성을 높이기 위해서이다.

질문에 대한 자료를 찾아보며 다음과 같은 등장 배경을 찾아볼 수 있었다.

람다를 지원하기 전의 자바는 클래스에서 메서드를 정의하고, 필요할 때 메서드를 호출하는 형태의 완전한 명령형 프로그래밍 패러다임을 고수하고 있었다.

그러나 자바를 사용하는 개발자들은 개발 규모가 커지면서 복잡하게 얽힌 코드를 유지보수 하는 것이 힘들어졌다.

모든 것을 순수 함수로 나누어 문제를 해결하는 함수형 프로그래밍 패러다임이 나타나면서 자바에서도 이러한 함수형 프로그래밍 패러다임의 이점을 가져오기 위해 람다식이 등장하게 되었다.

람다식을 이용하면 함수를 일급 객체로 다루어 함수형 프로그래밍의 패러다임을 자바에서도 적용할 수 있게 되었다.

즉, 람다식이 등장하며 자바는 객체지향 언어이며 함수형 언어의 기능을 갖추게 되었다고 할 수 있다.

그렇게 함수형 프로그래밍 패러다임을 통해 기존 코드에서 불필요한 코드를 줄이고, 가독성을 높일 수 있어 유지보수 측면에 도움이 되었다.

이러한 이유로 불필요한 코드를 줄이고, 가독성을 높이기 위해서 함수형 프로그래밍 패러다임을 도입하려 했고 그러기 위해 람다식이 등장했다는 것으로 이해했다.

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

A. 람다식과 익명 클래스는 공통적으로 함수형 프로그래밍을 지원하기 위해 익명 함수를 만드는데 사용되지만 다른 부분도 존재하며 주로 익명 클래스를 대체하여 더 간결하고 가독성 높은 코드를 작성하기 위해 람다식을 사용한다.

람다식

  • 이름이 없는 메서드입니다.

  • 추상 및 구체 클래스를 확장할 수 없습니다.

  • 단일 추상 메서드를 포함하는 인터페이스를 구현할 수 있습니다.

  • 인스턴스 변수를 선언할 수 없습니다.

  • 람다 표현식을 인스턴스화 할 수 없습니다.

  • 람다 표현식 내부의 this 키워드는 현재 외부 클래스 객체를 나타냅니다.

익명 클래스

  • 이름이 없는 클래스이다.

  • 추상 및 구체 클래스를 확장할 수 있다.

  • 여러 추상 메서드를 포함하는 인터페이스를 구현할 수 있다.

  • 익명 내부 클래스 내부에서 인스턴스 변수를 선언할 수 있다.

  • 익명 내부 클래스를 인스턴스화 할 수 있다.

  • 익명 내부 클래스 내부의 this 키워드는 현재 익명 내부 클래스 객체를 참조한다.

     

다른 부분이 있음에도 불구하고 람다식을 사용하는 이유는 람다식을 사용하면 익명 클래스를 사용한 것보다 더 간결하고 가독성 높은 코드를 작성할 수 있다.

예를 들어, 문자열 리스트를 정렬하는 예제를 익명 클래스와 람다식으로 구현한 과정을 비교해보겠다.

  • 익명 클래스

        Collections.sort(words, new Comparator<String>() {
            // 익명 클래스 정의
            public int compare(String s1, String s2) {
                return Integer.compare(s1.length(), s2.length());
            }
        });
  • 람다식

Collections.sort(words, (s1, s2) -> Integer.compare(s1.length(), s2.length()));

코드를 상당히 줄여주고 보기 편해진 것을 확인할 수 있다.

 

Q. 람다식의 문법은 어떻게 될까?

람다식은 기본적으로 매개변수(Parameter) 와 화살표(->)와 실행문(expression)으로 구성된다.

다음과 같은 매커니즘으로 람다식을 구현한다.

기본                        : (int num) -> {System.out.println(num);} 

단일 실행문은 중괄호 제거    : (int num) -> System.out.println(num);

단일 인자는 타입 생략        : (num) -> System.out.println(num);

단일 인자는 소괄호 제거      : num -> System.out.println(num);

인자가 없으면 소괄호 필수    : () -> System.out.println("매개변수 없음"); 

인자가 여러개면 소괄호 필수  : (x, y) -> System.out.println(x, y);

인자가 없고 반환값이 있으면  : () -> {return value;};

실행코드가 return문 뿐이면 return 키워드 생략 가능 : () -> value;

매개변수, 리턴타입 둘다 있으면 : (x, y) -> x+y;

 

[Java] 익명 클래스 (Anonymous Class)란? — 개발자의 서랍 (tistory.com)

[Java] Stream API -1 이해하기: 용어 및 Stream 생성 — Contributor9 (tistory.com)

코드 가독성 높이는 자바 람다식과 함수형 인터페이스 | 요즘IT (wishket.com)

[Java] 람다식(Lambda Expression)과 함수형 인터페이스(Functional Interface) - (2/5) - MangKyu's Diary (tistory.com)

[Java]익명 내부 클래스와 람다식의 차이점 (tistory.com)

람다식(feat. 익명 구현 클래스 vs 람다식) (tistory.com)

댓글을 작성해보세요.