진도표 3일차와 연결됩니다
우리는 JdbcTemplate을 사용하는 과정에서 익명 클래스와 람다식이라는 자바 문법을 사용했습니다. 익명 클래스는 자바의 초창기부터 있던 기능이고, 람다식은 자바 8에서 등장한 기능입니다. 다음 키워드를 사용해 몇 가지 블로그 글을 찾아보세요! 아래 질문을 생각하며 공부해보면 좋습니다! 😊
[키워드]
익명 클래스 / 람다 / 함수형 프로그래밍 / @FunctionalInterface / 스트림 API / 메소드 레퍼런스
[질문]
- 자바의 람다식은 왜 등장했을까?
- 람다식과 익명 클래스는 어떤 관계가 있을까? - 람다식의 문법은 어떻게 될까?
자바의 람다식 등장 배경
람다식이 등장하게 된 이유는 불필요한 코드를 줄이고, 가독성을 높이기 위함이다.
현재 실습하고 있는 '도서관리 애플리케이션'의 getmapping api 코드에서 람다식으로 바꾸기 전과 후를 비교해보자.
처음에는 database를 연결하지 않았을 때 getmapping 상태이다.
이를 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 명령문을 이용하여 인스턴스를 생성하는데, 이 때 참조타입을 상속하는 인터페이스(혹은 클래스)로 지정해야한다는 것에 유의하자.
- 익명 클래스의 멤버 사용 방법은 일반 클래스와 다르지 않다. 참조변수로 접근하여 사용한다.
그렇다면,
람다식과 익명 클래스는 어떤 관계가 있을까?
결과적으로 말하면, 람다식이 익명 클래스보다 간결하다.
public class Example {
interface Math {
int sum(int n1, int n2);
}
static class MyMath implements Math {
public int sum(int n1, int n2) {
reutrn n1 + n2;
}
}
static int doSomething(Math math) {
return math.sum(10, 20);
}
pulbic static void main(String[] args) {
Math math = new MyMath();
int result = doSomething(math);
System.out.println(result); // 30
}
}
public class Example2 {
interface Math {
int sum(int n1, int n2);
}
static int doSomething(Math math) {
return math.sum(10, 20);
}
public static void main(Stirng[] args) {
int result = doSomething((n1, n2) -> n1 + n2); // Lambda
System.out.println(result); // 30
}
}
위의 예제는 람다식을 사용하여 동일한 내용을 다시 구현한 것이다
익명 함수와 매우 비슷하지만 불필요한 선언부들이 모두 생략되어 있고, 인터페이스 함수의 구현부만 정의하고 있어 코드가 가장 간결하다
[출처]
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
https://yummy0102.tistory.com/661
'spring' 카테고리의 다른 글
[인프런 워밍업 클럽 6차 과제-5/11] 백엔드 (0) | 2024.05.11 |
---|---|
[인프런 워밍업 클럽 4차 과제-5/7] 백엔드 (1) | 2024.05.07 |
[인프런 워밍업 클럽 1차 과제-4/29] (0) | 2024.04.29 |
[쿠석쿠석 프로젝트] 코드리뷰 #1 데이터베이스 구조 설계 (0) | 2024.04.04 |
[스프링 부트] 회원 관리 세팅 및 테스트 케이스 작성 - 정리 (1) | 2024.03.14 |