[인프런 워밍업 클럽 스터디1기] 백엔드 - 3차 과제

[인프런 워밍업 클럽 스터디1기] 백엔드 - 3차 과제

진도표 3일차와 연결됩니다

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

 

[키워드]

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

 

[질문]

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

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

 

자바의 람다식 등장 배경

람다식이 등장하게 된 이유는 불필요한 코드를 줄이고, 가독성을 높이기 위함이다.

현재 실습하고 있는 '도서관리 애플리케이션'의 getmapping api 코드에서 람다식으로 바꾸기 전과 후를 비교해보자.

처음에는 database를 연결하지 않았을 때 getmapping 상태이다.  

 

database 연결 안된 상태

 

이를 database를 연결하면 아래와 같이 코드를 쓸 수 있다. 이때는 람다식을 적용하지 않았다.

 

람다식 적용하지 않고 database 연결

 

그후 람다식을 적용한 코드이다.

 

람다식 적용

 

겉으로는 new RowMapper 객체 선언과 @override 하여 정의하는 부분이 없어졌다. 
따라서 더 간결해진 코드를 만들 수 있어 가독성이 높아진다.

람다식과 익명 클래스는 어떤 관계

먼저 람다식 사용법에 대해 알아보자.

생략 가능한 부분이 많기 때문에 헷갈릴 수 있지만 대부분

(매개변수) -> {실행코드}

형식으로 작성된다.

(예시)

public interface Functional {
    int cal(int a, int b);
}

public interface Functional2 {
    void print(String str);
}

public interface Functional3 {
    void noArgs();
}

// 1. 작성 가능한 모든 내용을 생략 없이 작성한 경우     
Functional2 functional2 = (String name) -> { System.out.println(name) };

// 2. 매개변수의 타입을 생략한 경우   
Functional2 functional2 = (name) -> { System.out.println(name) };    

// 3. 매개변수가 한개여서 소괄호를 생략한 경우    
Functional2 functional2 = name -> { System.out.println(name) };          

// 4. 실행 코드가 한 줄이어서 중괄호를 생략한 경우    
Functional2 functional2 = name -> System.out.println(name);    

// 5. 매개변수가 없어서 소괄호를 생략할 수 없는 경우    
Functional3 functional3 = () -> System.out.println("functiona3");    

// 6. 반환값이 있는 경우 return 키워드 사용하는 경우     
Functional functional = (a, b) -> {
       System.out.println("print");
       return a+b;
};

// 7. 실행 코드가 반환 코드만 존재하는 경우 키워드와 중괄호 생략한 경우    
Functional functional = (a, b) -> a+b;

 

그렇다면 익명 클래스는 무엇일까?

프로그램에서 일시적으로 한번만 사용되고 버려지는 객체이므로 재사용이 되지 않아 이름이 없는 클래스이다.

즉, 딱 한번만 인스턴스를 생성하기 위해서 선언되는 것이다.

 

익명 클래스(익명 객체)를 구현하는 방법은 아래와 같다.

// 선언 방법 
인터페이스명 변수명 = new 인터페이스명() {
		인터페이스의 메서드 오버라이딩
}

 

// MessengerTest.java
public class MessengerTest {
    public static void main(String[] args) {
        /* 일반 클래스의 인스턴스 생성과 사용 */
        GalaxyMessenger galaxy = new GalaxyMessenger();
        System.out.println(galaxy.getMessage());
        galaxy.setMessage("Hi, I'm Galaxy.");
        galaxy.changeKeyboard();

        /* 익명 클래스의 선언과 사용 */
        Messenger anonymousTest = new Messenger() { // 익명 클래스 선언

            @Override
            public String getMessage() { // 인터페이스 메서드 오버라이딩
                return "anonymousTest";
            }

            @Override
            public void setMessage(String msg) { // 인터페이스 메서드 오버라이딩
                System.out.println("anonymousTest에서 메시지를 설정합니다: " + msg);
            }
        };

        // 익명 클래스의 멤버 사용 
        System.out.println(anonymousTest.getMessage());
        anonymousTest.setMessage("Have a nice day!");
    }
}
  • GalaxyMessenger 클래스는 앞서 표시한 Messenger 인터페이스를 구현하는 일반 클래스이다. new 명령문을 이용하여 인스턴스를 생성하였다.

  • 익명 클래스 또한 new 명령문을 이용하여 인스턴스를 생성하는데, 이 때 참조타입을 상속하는 인터페이스(혹은 클래스)로 지정해야한다는 것에 유의하자.

  • 익명 클래스의 멤버 사용 방법은 일반 클래스와 다르지 않다. 참조변수로 접근하여 사용한다.

 


그렇다면, 

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

 

익명 함수와 매우 비슷하지만 불필요한 선언부들이 모두 생략되어 있고, 인터페이스 함수의 구현부만 정의하고 있어 코드가 가장 간결하다

 

즉, 같은 역할을 할 수 있지만 람다식이 더 간단하게 쓸 수 있는 것이다.

 

[출처]

https://wonyong-jang.github.io/java/2021/03/12/Java-Lambda-Expressions.html

 

https://limkydev.tistory.com/226

 

https://velog.io/@balparang/Java-%EC%9D%B5%EB%AA%85-%ED%81%B4%EB%9E%98%EC%8A%A4Anonymous-Class

댓글을 작성해보세요.