[이펙티브 자바] 아이템 42. 익명 클래스보다는 람다를 사용하라

June·2022년 3월 13일
0

[이펙티브자바]

목록 보기
37/72

예전에는 함수 타입을 표현할 때 추상 메서드를 하나만 담은 인터페이스를 사용했다. 이런 인터페이스의 인스턴스를 함수 객체라했다. JDK 1.1부터는 함수 객체를 만드는 주요 수단은 익명클래스였다.

익명 클래스의 인스턴스를 함수 객체로 사용

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

자바 8에 와서 추상 메서드 하나짜리 인터페이스는 특별한 대우를 받는다. 함수형 인터페이스라 부르는 이 인터페이스들의 인스턴스를 람다식을 사용해 만들수 있게 된 것이다. 

**람다식 - 익명 클래스 대체**
``` java
Collections.sort(words, (s1, s2) -> Integer.compare(s1.length(), s2.length()));

컴파일러가 문맥을 사렾 타입을 추론해준 것이다. 타입을 명시해야 코드가 더 명확할 때만 제외하고는, 람다의 모든 매개변수 타입은 생략하자.

람다 자리에 비교자 생성 메서드를 사용하면 이 코드를 더 간결하게 만들 수 있다 (아이템 14, 43).

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

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

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

람다를 이용하면 함수 객체를 실용적으로 사용할 수 있다.

public enum Operation {
    PLUS("+", (x, y) -> x+y);
    MINUS("-", (x,y) -> x-y);
    TIMES("*", (x,y) -> x*y);
    DIVIDE("/", (x,y) -> x / y);
    
    private final String symbol;
    private final DoubleBinaryOperator op;
    
    Operation(String symbol, DoubleBinaryOperator op) {
        this.symbol = symbol;
        this.op = op;
    }
    
    @Override
    public String toString() {
        return symbol;
    }
    
    public double apply(double x, double y) {
        return op.applyAsDouble(x, y);
    }
}

열거 타입의 동작을 표현한 람다를 DoubleBinaryOperator 인터페이스 변수에 할당했다. DoubleBinaryOperatorjava.util.function 패키지가 제공하는 함수 인터페이스(아이템 44)중 하나다.

람다 때문에 클래스 몸체는 더 이상 사용할 이유가 없다고 느낄 지 모르지만 그렇지 않다.
람다는 이름이 없고 문서화도 못한다. 코드 자체로 동작이 명확히 설명되지 않거나 코드 줄 수가 많아지면 사용하지 말아야 한다.

람다로 대체할 수 없는 곳들이 있다. 람다는 함수형 인터페이스에서만 쓰인다.

  • 추상 클래스의 인스턴스를 만들 때 람다를 쓸 수 없으니, 익명클래스를 써야한다.
  • 비슷하게도 추상 메서드가 여러 개인 인터페이스의 인스턴스를 만들 때도 익명 클래스를 쓸 수 있다.
  • 마지막으로 람다는 자신을 참조할 수 없다. 람다의 this는 바깥 인스턴스를 가리킨다. 익명 클래스의 this는 익명 클래스 인스턴스 자신이다. 그래서 자신을 참조해야할 경우 익명클래스를 써야 한다.

람다도 익명 클래스처럼 직렬화 형태가 구현별로 다를 수 있어, 람다를 직렬화하는 일은 하지 말아야한다.

0개의 댓글