익명 클래스는 무엇일까?
- 람다가 나오기 이전, 자바에서 함수 객체를 만드는 주요 수단
- '낡은' 기법이다.
//익명 클래스 예시
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()));
- 컴파일러가 문맥을 대신 살펴 람다식의 타입을 추론한다. (상황에 따라 프로그래머가 직접 명시해야 할 수도 있음)
- 매개변수 타입은 String, 반환값 타입은 int, 람다 타입은 Comparator<String>
- 타입을 직접 명시해야 코드가 더 명확한 경우를 제외하고는 람다의 모든 매개변수 타입은 생략해도 좋다.
위 예시는 비교자 생성 메서드 또는 sort 메서드를 사용하면 더 간단해질 수 있다.
비교자 생성 메서드
Collections.sort(words, comparingInt(String::length));
sort 메서드
words.sort(comparingInt(String::length));
람다를 활용해 열거 타입의 apply 메서드를 재정의해보자.
"기존"
PLUS("+"){ public double apply(double x, double y) {return x+y;}}
"lambda"
PLUS("+", (x, y) -> x + y)
- 람다를 이용하면 열거 타입 인스턴스 필드를 이용하는 방식으로 상수별로 다르게 동작하는 코드를 쉽게 구현할 수 있다.
-> 열거 타입 상수의 동작을 람다로 구현해 생성자에 넘기고, 생성자는 람다를 인스턴스 필드로 저장한다.
-> apply 메서드에서 필드에 저장된 람다를 호출하는 방식으로 깔끔히 구현할 수 있다.
그러나!

메서드와 클래스와 다르게 람다는 이름이 없고 문서화를 할 수 없다.
따라서, 코드 자체로 동작이 명확히 설명되지 않거나, 코드 길이가 길어질 경우 람다를 쓰지 않는 것이 좋다.
람다 사용 코드의 최적 길이 : 1~3
그럼 익명 클래스는 언제 써야 할까?
1. 함수형 인터페이스가 아닌 곳에 쓰면 된다.
- 람다는 함수형 인터페이스에서만 쓰이기 때문이다.
- 추상 메서드가 여러개인 인터페이스, 추상 클래스의 인스턴스 등.
2. 객체가 자신을 참조하는 경우에 사용한다.
- 익명 클래스의 this는 익명 클래스의 인스턴스 자기 자신을 가리킨다.
- 그러나 람다에서의 this 키워드는 자기 자신이 아닌 바깥 인스턴스를 가리킨다.
! 주의사항 !
람다와 익명 클래스 모두 직렬화 형태가 구현별로 다를 수 있다. 따라서 직렬화 하는 일은 삼가도록 하자!
핵심 정리
함수형 인터페이스가 아닌 타입의 인스턴스를 만들 때,
또는 객체가 자기 자신을 참조할 때는 익명 클래스를 사용하자.
이런 경우가 아니라면 람다를 사용하자.
'JAVA > Effective Java' 카테고리의 다른 글
item 44. 표준 함수형 인터페이스를 사용하라 (0) | 2022.06.18 |
---|---|
item 43. 람다보다는 메서드 참조를 사용하라 (0) | 2022.06.17 |
item 41. 정의하려는 것이 타입이라면 마커 인터페이스를 사용하라 (0) | 2022.06.14 |
item 40. @Override 애너테이션을 일관되게 사용하라 (0) | 2022.06.12 |
item39. 명명 패턴보다 애너테이션을 사용하라 (0) | 2022.06.03 |
댓글