이펙티브 자바라는 책을 읽던 중 람다 함수에 대해 궁금하여 정리해보았습니다.
간단하게 문자열을 길이 순으로 정렬하는데, 정렬을 위한 비교 함수로 익명 클래스로 사용한 방법을 확인해봅시다.
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
이 코드에서 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는 익명 클래스의 인스턴스 자신을 가리킵니다. 그래서 함수 객체가 자신을 참조해야 한다면 반드시 익명 클래스를 사용해야 합니다.
'혼자 공부하는 것들 > JAVA' 카테고리의 다른 글
Java11 람다식에서 VAR를 사용할 수 있다고? (0) | 2022.07.02 |
---|---|
가변인수는 신중하게! (3) | 2022.03.16 |
[동시성 이슈해결] HashMap보다는 ConcurrentHashMap을 쓰자! (0) | 2022.01.01 |
서블릿의 라이프 사이클 (0) | 2021.12.29 |
맥북 자바 버전 변경하는 방법 (0) | 2021.12.10 |
댓글