본문 바로가기
JAVA/Effective Java

item 42. 익명 클래스보다는 람다를 사용하라

by Garonguri 2022. 6. 14.
728x90

익명 클래스는 무엇일까?

- 람다가 나오기 이전, 자바에서 함수 객체를 만드는 주요 수단

- '낡은' 기법이다.

//익명 클래스 예시

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 키워드는 자기 자신이 아닌 바깥 인스턴스를 가리킨다.

 


! 주의사항 ! 

람다와 익명 클래스 모두 직렬화 형태가 구현별로 다를 수 있다. 따라서 직렬화 하는 일은 삼가도록 하자!

 

 

핵심 정리

함수형 인터페이스가 아닌 타입의 인스턴스를 만들 때,
또는 객체가 자기 자신을 참조할 때는 익명 클래스를 사용하자.

이런 경우가 아니라면 람다를 사용하자.

 

 

728x90

댓글