3. 람다 표현식의 실사용
# 2. 람다.
람다는 더 간결하고 유연한 코드를 작성할 수 있게 도와준다. 람다의 특징은 아래와 같다.
람다 표현식은 메서드로 전달할 수 있는 익명 함수를 단순화한 것이라고 할 수 있다. 람다 표현 식에는 이름은 없지만, 파라미터 리스트, 바디, 반환 형식, 발생할 수 있는 예외 리스트는 가질 수 있다
- 익명 : 메서드와 달리 이름이 없다 따라서 구현해야할 코드가 줄어든다.
- 함수 : 메서드처럼 클래스에 종속되지 않으므로 함수라고 부른다. 하지만 약간의 형식은 가지고 있다.
- 전달 : 메서드의 인수로 전달하거나 변수로 저장이 가능하다.
- 간결성 : 그냥 동작에 필요한 코드가 전부이다.(익명 클래스처럼 아무 이름이나 짓고 내부에 메서드 시그니처까지 다 적어야하는 수고로움이 없다.
Comparator<Apple> byWeight = new Comparator<Apple>() { public int compare(Apple a1, Apple a2) {
return a1.getWeight().compareTo(a2.getWeight());
}
};
Comparator<Apple> byWeight = ((Apple a1, Apple a2) -> a1.getWeight.compareTo(a2.getWeight());
위의 코드를 보면 Comparator의 compare 메서드를 오버라이딩해서 사용하는 함수이다. 하지만 람다를 사용하면 하단부와 같이 사용할 수 있다.
람다 표현식은 세부분으로 나눠져있다.
인자로 사용할 리스트와 리스트와 바디를 구분하는 화살표 그리고 행위를 표현하는 바디 이다.
람다에는 두가지 기본적인 표현식이있다. 아래 와 같다.
(parameter) -> expression ====> 표현식
(parameter) -> {statement;} ====> 블럭 스타일
- () -> {} ------- 정답
- () -> "Raoul" ------- 정답
- () -> {return "Mario";} ------- 정답
- (Integer i) -> return "Alan" + i; --------- (Integer i) -> {return "Alan" + i ;} 명시적 Return 표현시 블럭 내부에 가는게 맞다.
- (String s) -> {"Iron Man";} ----- (String s) -> "Iron Man" 표현식으로 쓰는게 맞다.
# 3. 그럼 이 람다를 어디에 어떻게 써야할까?
1. 함수형 인터페이스
추상 메서드가 오직 하나인 인터페이스를 의미하며 @FunctionalInterface 필요.
함수형 인터페이스는 단 하나의 추상 메서드가 존재하는 인터페이스를 의미한다.(아예 없으면 안된다.) 디폴트 메서드가 아무리 여러개 존재해도 추상 메서드가 하나 존재한다면 함수형 인터페이스이다. 또한 어떠한 상속도 받으면 안된다.
람다를 통해 함수형 인터페이스의 추상메서드의 구현부분을 주입하고 전체 표현식을 함수형 인터페이스의 구현체(인스턴스)로 취급한다.
함수 디스크립터 : 람다 표현식의 시그니처를 서술하는 추상 메서드의 시그니처들이다. 이를 함수 디스크립터라고 말한다.
()->void : 파라미터가 없고 void형을 반환하는(아무것도 반환하지 않는 함수를 의미)
(A,b)-> int: a,b를 인수로 받아 int형을 반환하는 함수
람다 표현식은
1. 변수에 할당가능,
2. 함수형 인터페이스를 인수로 받는 메서드로 전달할 수 있다.
3. 함수형 인터페이스의 추상 메서드와 같은 시그니처를 갖는다.
한개의 void 메소드 호출은 중괄호로 감쌀 필요가 없다.
실행 어라운드 패턴
실제 로직을 설정과 정리 두 과정이 둘러싸는 형태를 갖는 것을 의미한다.
함수형 인터페이스 실사례
자바에는 직접 정의내려 사용하지 않고 바로 사용할 수 있는 함수형 인터페이스가 몇가지 있다.
Predicate, Consumer, Function deli.
Predicate<T> : T 객체를 받아서 boolean 값을 받아서 반환해주는 test(T t)를 가지고 있다. (T t)-> boolean
Consumer<T> : T형식의 객체를 받아 어떤 동작만 수행하고 void를 반환해주는 accept(T t) 객체가 있다.
Function<T, R> : 제네릭 T객체를 인수로 받고 제네릭 R객체를 반환하는 추상 메서드 [R apply(T t)]를 제공
제네릭 내부구현때문에 참조형만 사용 가능, 따라서 자바에서는 기본형을 참조형으로 변환해주는 박싱과 그 반대로 만들어주는 언박싱, 프로그래머가 편하게 사용할 수 있도록 오토박싱을 지원한다.
하지만 이 박싱의 과정은 비용이 소모된다. 래핑은 기본형을 래퍼로 감싸는 행위이다. 따라서 메모리를 더 소비한다. 이러한 것들을 소모를 막기위해 함수형 인터페이스에는 오토박싱을 피할 수 있는 함수형 인터페이스를 제공한다.