일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- 자료형
- ArrayList
- 배열
- 졸리다
- 초보개발자
- exception
- 백엔드
- 파이팅
- 문자 단위 스트림
- 인터페이스
- 바이트 단위 스트림
- 코린이
- throws
- 변수
- 예외 처리
- Java
- MPA
- 자바
- FileInputStream
- 개발자
- 보조 스트림
- try-catch
- 새벽공부
- 상속
- 다형성
- node.js
- SSR
- 코딩
- 인스턴스
- 메서드
- Today
- Total
SHUSTORY
13-2 람다식 본문
함수형 프로그래밍과 람다식
자바는 객체 기반 프로그램 구현 방식으로, 어떤 기능이 필요할 경우 클래스를 만든 후 클래스 내부에 기능을 구현한 메서드를 만들고 해당 메서드를 호출한다.
그런데 프로그래밍 언어 중 함수의 구현과 호출만으로 프로그램을 만들 수 있는 프로그래밍 방식이 있는데, 이를 '함수형 프로그래밍'이라고 한다.
자바에서도 함수형 프로그래밍을 지원하는데, 이를 '람다식'이라고 한다.
함수가 입력받은 자료 외의 외부 자료에 영향을 미치지 않기 때문에 여러 자료를 동시에 처리하는 병렬 처리에 적합하며, 안정되고 확장성 있는 프로그램을 개발할 수 있는 장점이 있다.
람다식 구현하기
람다식은 앞서 구현했던 프로그래밍 방식과는 다르다.
간단히 설명하자면, 함수 이름이 없는 익명 함수를 만드는 것으로, 람다식 문법은 다음과 같다.
예를 들어 두 수를 입력받아 그 합을 반환하는 add( ) 함수를 기존 방식과 람다식 방식으로 만들어 비교해 보자.
람다식에서는 위와 같이 메서드 이름 add와 반환형 int를 없애 간결하게 구현하였다.
람다식 문법 살펴보기
- 매개변수 자료형과 괄호 생략하기
- 람다식 문법에서는 매개변수 자료형을 생략할 수 있으며, 매개변수가 하나일 경우 괄호도 생략 가능하다.
- 단, 매개변수가 두 개인 경우 괄호를 생략할 수 없다.
- 람다식 문법에서는 매개변수 자료형을 생략할 수 있으며, 매개변수가 하나일 경우 괄호도 생략 가능하다.
- 중괄호 생략하기
- 중괄호 안의 구현 부분이 한 문장인 경우 중괄호를 생략할 수 있다.
- 중괄호 안의 구현 부분이 한 문장이더라도 return문은 중괄호를 생략할 수 없다.
- 중괄호 안의 구현 부분이 한 문장인 경우 중괄호를 생략할 수 있다.
- return 생략하기
- 중괄호 안의 구현 부분이 return문 하나라면 중괄호와 return을 모두 생략하고 식만 쓴다.
람다식 사용하기
두 수 중 큰 수를 찾는 함수를 람다식으로 구현해보자.
람다식을 구현하기 위해서는 먼저 인터페이스를 만들고, 인터페이스에 람다식으로 구현할 메서드를 선언한다.
이를 함수형 인터페이스라고 한다.
MyNumber 함수형 인터페이스를 만들고 내부에 getMax( ) 추상 메서드를 선언한다.
람다식을 구현할 때 생략할 수 있는 부분은 되도록 생략하여 구현한다.
함수형 인터페이스
람다식은 메서드 이름이 없고 메서드를 실행하는 데 필요한 매개변수와 매개변수를 활용한 실행 코드를 구현하는 것이다.
그렇다면 메서드는 어디에 선언하고 구현해야 할까?
함수형 언어에서는 함수만 따로 호출할 수 있지만, 자바에서는 참조 변수 없이 메서드를 호출할 수 없다.
그러므로 람다식을 구현하기 위해 함수형 인터페이스를 만들고, 인터페이스에 람다식으로 구현할 메서드를 선언한다.
람다식은 하나의 메서드를 구현하여 인터페이스형 변수에 대입하므로
인터페이스가 두 개 이상의 메서드를 가져서는 안 된다.
람다식은 이름이 없는 익명 함수로 구현하기 때문에 인터페이스에 메서드가 여러 개 있다면 어떤 메서드를 구현할 것인지 모호해진다. 따라서 람다식은 오직 하나의 메서드만 선언한 인터페이스를 구현할 수 있다.
@FunctionalInterface 애노테이션
프로그래밍 도중 람다식으로 구현한 인터페이스에 실수로 다른 메서드를 추가하는 실수를 막기위해 @FunctionalInterface 애노테이션을 사용한다. 이는 함수형 인터페이스라는 의미로, 메서드를 하나 이상 선언할 경우 오류가 발생한다.
이는 반드시 작성해야 하는 것은 아니지만, 이후 발생할 오류를 방지할 수 있다.
객체 지향 프로그래밍 방식과 람다식 비교
문자열 두 개를 쉼표로 연결해서 출력하는 예제를 기존의 객체 지향 프로그래밍 방식과 람다식 방식으로 구현해보자.
람다식을 사용할 경우 클래스에 메서드의 구현부를 만들고, 이를 다시 인스턴스로 생성하고 호출하는 코드를 생략할 수 있어 코드가 간결해진다.
다음은 객체 지향 프로그래밍과 람다식 예제에서 사용할 인터페이스이다.
객체 지향 프로그래밍 방식으로 구현_클래스에서 인터페이스 구현하기
인터페이스의 추상 메서드를 StringConcatImpl 클래스에서 재정의하고,
StringConcat 인터페이스를 구현한 StringConcatImpl 클래스를 인스턴스로 생성하여 참조변수 concat1을 사용해 makeString( ) 메서드를 호출하였다.
람다식 방식으로 구현_람다식으로 인터페이스 구현하기
StringConcat 인터페이스 자료형인 concat2 변수에 대입하고, 이 변수를 사용하여 makeString( ) 메서드를 호출한다.
두 방식을 비교해보면, 람다식으로 구현하는 경우 코드가 훨씬 간결해지는 것을 볼 수 있다.
람다식으로 구현하려면 메서드를 하나만 포함하는 함수형 인터페이스만 가능하다는 것을 주의하도록 하자.
익명 객체를 생성하는 람다식
앞서 배운 익명 내부 클래스는 클래스 이름 없이 인터페이스 자료형 변수에 바로 메서드 구현부를 생성하여 대입할 수 있었다.
즉 람다식으로 메서드를 구현해서 호출하면 컴퓨터 내부에서는 다음처럼 익명 클래스가 생성되고 이를 통해 익명 객체가 생성되는 것이다.
람다식에서 사용하는 지역 변수
두 문자열을 연결하는 람다식 코드에서 외부 메서드의 지역 변수를 수정하면 어떻게 될까?
오류가 발생한다.
* 출력만 하는 경우는 오류가 발생하지 않는다.
지역 변수는 메서드 호출이 끝나면 메모리에서 사라지기 때문에 익명 내부 클래스에서 사용하는 경우에는 지역 변수가 상수로 변한다. 람다식 역시 익명 내부 클래스가 생성되므로 외부 메서드의 지역 변수를 사용하면 변수는 final 변수, 즉 상수가 되므로 이 변수를 변경하면 오류가 발생한다.
함수를 변수처럼 사용하는 람다식
람다식을 이용하면 구현된 함수를 변수처럼 사용할 수 있다.
우리가 프로그램에서 변수를 사용하는 경우는 크게 다음 세 가지가 있다.
- 특정 자료형으로 변수 선언 후 값 대입하여 사용하기
- 매개변수로 전달하기
- 메서드의 반환 값으로 반환하기
람다식으로 구현된 메서드도 변수에 대입하여 사용할 수 있고, 매개변수로 전달하고 반환할 수 있다.
인터페이스형 변수에 람다식 대입하기
인터페이스에 메서드 하나를 선언한 후
이를 실행하기 위해 인터페이스형 변수를 선언하고 여기에 람다식 구현부를 대입한다.
람다식이 대입된 변수 lamdaStr를 사용하여 람다식 구현부를 호출할 수 있다.
매개변수로 전달하는 람다식
람다식을 변수에 대입하면 이를 매개변수로 전달할 수 있다.
이때 전달되는 매개변수의 자료형은 인터페이스형이다.
반환 값으로 쓰이는 람다식
메서드의 반환형을 람다식의 인터페이스형으로 선언하면 구현한 람다식을 반환할 수 있다.
람다식은 마치 변수를 사용하듯
함수의 구현부를 변수에 대입하고, 매개변수로 전달하고, 함수의 반환 값으로 사용할 수 있다.
최근 자바에는 제네릭이나 람다식 같은 개념을 모르면 이해하기 어려운 코드를 종종 볼 수 있기 때문에
이와 관련된 개념을 익히도록 하자.
'프로그래밍 > JAVA' 카테고리의 다른 글
14-2 예외 처리하기 (0) | 2023.03.16 |
---|---|
14-1 예외 클래스 (0) | 2023.03.16 |
13-1 내부 클래스 (0) | 2023.03.13 |
12-5 Map 인터페이스 (0) | 2023.03.08 |
12-4 Set 인터페이스 (0) | 2023.03.08 |