JAVA/Effective Java

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

Garonguri 2022. 6. 14. 19:05
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