본문 바로가기
혼자 공부하는 것들/JAVA

익명 클래스하고 람다식은 어떤 상황일 때 사용해야할까?

by applepick 2022. 3. 10.
반응형

이펙티브 자바라는 책을 읽던 중 람다 함수에 대해 궁금하여 정리해보았습니다. 

 

간단하게 문자열을 길이 순으로 정렬하는데, 정렬을 위한 비교 함수로 익명 클래스로 사용한 방법을 확인해봅시다.

Collections.sort(words, new Comparator<String>(){
    public int compare(String s1, String s2){
        return Integer.compare(s1.length(), s2.length());
    }
});

전략 패턴처럼 함수 객체를 사용하는 과거 객체지향 디자인 패턴에는 익명 클래스면 충분했습니다.

https://ko.wikipedia.org/wiki/%EC%A0%84%EB%9E%B5_%ED%8C%A8%ED%84%B4

 

전략 패턴 - 위키백과, 우리 모두의 백과사전

전략 패턴(strategy pattern) 또는 정책 패턴(policy pattern)은 실행 중에 알고리즘을 선택할 수 있게 하는 행위 소프트웨어 디자인 패턴이다. 전략 패턴은 특정한 계열의 알고리즘들을 정의하고 각 알고

ko.wikipedia.org

이 코드에서 Comparator 인터페이스가 정렬을 담당하는 추상 전략을 말하며, 문자열을 정렬하는 구체적인 전략을 익명 클래스로 구현했습니다. 자바 8에서 람다와 함수형 인터페이스 메서드 참조라는 개념이 추가되면서 함수 객체를 더 쉽게 만들 수 있게 되었습니다.

Collections.sort(words,
        (s1,  s2) -> Integer.compare(s1.length(), s2.length()));

 

여기서 람다, 매개변수(s1, s2)의 반환 값의 타입은 각 각 Compartor <String>, String, int지만 코드에서 찾아볼 수 없습니다. 컴파일러가 문맥을 살펴 타입을 추론해준 것입니다. 타입을 명시해야 코드가 더 명확할 때만 제외하고는, 람다의 모든 매개변수 타입은 생략하는 게 좋습니다. 컴파일러가 타입을 추론하는 데 필요한 타입 정보 대부분을 제네릭에서 얻습니다. 결국 이 정보를 제공하지 않으면 컴파일러는 람다의 타입을 추론할 수 없게 되어, 결국 우리가 일일이 명시해줘야합니다.(코드가 지저분해질 수 있습니다.)

 

여기서 비교자 생성 메서드를 사용하면 더 코드를 간결하게 만들 수 있습니다.

Collections.sort(words, comparingInt(String::length));

 

더 나아가 자바 8 때 List 인터페이스에 추가된 sort 메서드를 사용하면 

words.sort(comparingInt(String::length));

조금 더 간결하게 작성할 수 있습니다. 

 

하지만, 람다로 대체할 수 없는 것이 있습니다. 람다는 함수형 인터페이스에서만 사용됩니다. 하나의 예로, 추상 클래스의 인스턴스를 만들 때 람다를 쓸 수 없으니, 익명 클래스를 사용해야합니다. 또한, 람다는 자신을 참조할 수 없습니다. 람다에서의 this 키워드바깥 인스턴스를 가르킵니다. 반면 익명 클래스에서의 this는 익명 클래스의 인스턴스 자신을 가리킵니다. 그래서 함수 객체가 자신을 참조해야 한다면 반드시 익명 클래스를 사용해야 합니다. 

반응형

댓글