[Effective Java] 익명 클래스보다는 람다를 사용하라

들어가며

자바8 부터 람다를 통해 함수형 인터페이스를 대체할 수 있게 되었다. 람다식으로 작성된 코드는 컴파일러가 타입을 추론해준다. 타입을 명시해야 코드가 더 명확할 때를 제외하고는 람다의 모든 매개변수 타입은 생략해야 한다. 다음은 익명 클래스를 람다로 바꾼 코드이다.

1
2
3
4
5
Collections.sort(words, new Comparator<String>() {
public int compare(String s1, String s2) {
return Integer.compare(s1.length(), s2.length());
}
});
1
Collections.sort(words, (s1, s2) -> Integer.compare(s1.length(), s2.length()));

람다 자리에 비교자 생성 메소드나 자바8 부터 List 인터페이스에 추가된 sort 메소드를 활용하면 코드를 더 간결하게 짤 수 있다.

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

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

다음 코드는 int 상수 대신 열거 타입을 사용하라에서 만든 enum 클래스를 람다로 교체한 예시이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public enum Operation {
PLUS("+", (x,y) -> x + y),
MINUS("-", (x,y) -> x - y);

private final String symbol;
private final DoubleBinaryOperator op;

Operation(String symbol, DoubleBinaryOperator op) {
this.symbol = symbol;
this.op = op;
}

public double apply(double x, double y) {
return op.applyAsDouble(x, y);
}
}

람다는 다음과 같은 사항을 주의해야 한다. 람다는 이름이 없고 문서화도 못한다. 따라서 코드 자체로 동작이 명확히 설명되지 않거나 코드 줄 수가 많아지면 람다를 쓰지 말아야 한다. 또한 람다는 함수형 인터페이스에서만 쓰인다. 예를 들어 추상 클래스의 인스턴스를 만들 때 람다는 쓸 수 없으니 익명 클래스를 써야한다. 람다는 자기 자신을 참조할 수 없다. 익명 클래스 내에서 this는 익명 클래스 인스턴스 자신이다. 하지만 람다 내에서의 this는 바깥 인스턴스를 가리킨다. 람다를 직렬화 하는 일은 삼가야 한다.람다도 익명클래스처럼 직렬화 형태가 구현별이나 VM별로 다를 수 있다. 반드시 직렬화 해야하는 함수 객체가 있다면 private static nested class의 인스턴스를 사용하자.

Author: Song Hayoung
Link: https://songhayoung.github.io/2020/08/15/Languages/Effective%20JAVA/item42/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.