Java/Effective Java
[Effective Java] Item 42. 익명 클래스보다는 람다를 사용하라
안도일
2023. 7. 2. 17:37
익명 클래스
- 자바에서 익명 클래스는 이름이 없는 클래스로, 일회성으로 사용되는 클래스를 간편하게 정의할 수 있는 기능이다.
- 익명 클래스는 클래스 선언과 동시에 인스턴스를 생성하여 사용한다.
- 주로 인터페이스나 추상 클래스를 구현하거나 확장하는 데 사용되는데, 이를 이용하면 클래스를 별도로 정의하고 이름을 부여하지 않고도 필요한 구현을 작성할 수 있다.
익명 클래스 예
문자열을 길이순으로 정렬하는데, 정렬을 위한 비교 함수로 익명 클래스를 사용하였다.
람다
익명 클래스 방식은 코드가 너무 길기 때문에 람다식을 이용해 어떤 동작을 하는지 명확하게 나타낼 수 있도록 하자.
람다식을 함수 객체로 사용한 예제
위 익명 클래스로 작성한 정렬을 람다식으로 대체한 예제이다.
- 람다, 매개변수, 반환값의 타입은 각각 Comparator<String>, String, int 이지만 코드에서는 언급이 없다.
- 컴파일러가 문맥을 살펴 타입을 추론해준다.
- 컴파일러는 타입 정보 대부분을 제네릭에서 얻기 때문에 앞서 살펴본 Item 26, 29, 30의 조언을 명심하자.
- 컴파일러가 타입을 알 수 없다는 오류를 낼 때만 해당 타입을 명시하면 된다.
함수 객체(람다)를 인스턴스 필드에 저장해 상수별 동작을 구현한 열거 타입
- 각 열거 타입 상수의 동작을 람다로 구현해 생성자에 넘기고, 생성자는 이 람다를 인스턴스 필드로 저장해 둔다.
- 그 후 apply 메서드에서 필드에 저장된 람다를 호출하면 상수별 클래스 몸체를 구현하는 방식보다 깔끔하게 구현할 수 있다.
람다의 단점
1. 람다는 메서드와 클래스와 달리 이름이 없고 문서화도 할 수 없다.
- 코드 자체로 동작이 명확히 설명되지 않거나 코드 줄 수가 많아지면 람다를 쓰지 말아야 한다.
- 한 줄 일 때 가장 좋고 세 줄 안에 끝내는 게 좋다.
2. 인스턴스는 런타임에 만들어지기 때문에 열거 타입 생성자 안의 람다는 인스턴스 멤버에 접근할 수 없다.
- 인스턴스 필드나 메서드를 사용해야만 하는 상황이거나 코드가 길어진다면 상수별 클래스 몸체(Item 34 상수별 메서드 구현을 상수별 데이터와 결합 예제)를 사용하자.
3. 람다는 함수형 인터페이스 (딱 하나의 추상 메서드를 가지는 인터페이스)에서만 사용된다.
- 추상 클래스의 인스턴스를 만들 때 람다를 쓸 수 없다.
4. 자기 자신을 참조할 수 없다.
- 람다에서의 this 키워드는 바깥 인스턴스를 가리킨다.
- 함수 객체가 자신을 참조해야 한다면 익명 클래스를 쓰자.
5. 직렬화 형태가 구현별로 (가상머신) 다를 수 있다.
- 람다를 직렬화하는 일은 삼가자. (익명 클래스의 인스턴스도 마찬가지다.)
- 직렬화해야만 하는 함수 객체가 있다면 private 정적 중첩 클래스의 인스턴스를 사용하자.
결론
- 람다는 작은 함수 객체를 아주 쉽게 표현할 수 있다.
- 익명 클래스는(함수형 인터페이스가 아닌) 타입의 인스턴스를 만들 때만 사용하자.