[Effective Java] 아이템42 - 익명 클래스보다는 람다를 사용하라
7장에서는 람다와 스트림에 대해서 알아본다.
람다가 나오기 이전에는 자바에서 함수 타입을 표현할 때 추상 메서드를 하나만 담은 인터페이스를 사용했다. 이 인터페이스를 익명클래스로 구현해서 함수 객체로 사용했다.
Collections.sort(words, new Comparator<String>() {
public int compare(String s1, String s2) {
return Integer.compare(s1.length(), s2.length());
}
});
람다로 위와 같은 코드를 훨씬 짧게 만들 수 있다.
Collections.sort(words, (s1, s2) -> Integer.compare(s1.length(), s2.length()));
여기서 람다객체, 매개변수 (s1,s2)와 반환값의 타입은 각각 (Comparator
컴파일러가 타입을 추론하는데 필요한 타입 정보 대부분을 제네릭에서 얻기 때문에, 제네릭과 람다를 함께 쓸 때는 제네릭의 힘이 더 중요해진다.
람다 자리에 비교자 생성 메서드를 사용하면 코드를 더 간결하게 할 수 있다.
Collections.sort(words, comparingInt(String::length));
아이템34에서 Operation
열거타입을 상수별 클래스 몸체에 각 상수별로 다르게 동작하는 apply 메서드를 작성했던 것을 다시보자
public enum BasicOperation implements Operation{
PLUS("+") {
public double apply(double x, double y) { return x + y; }
},
MINUS("-") {
public double apply(double x, double y) { return x - y; }
},
TIMES("*") {
public double apply(double x, double y) { return x * y; }
},
DIVIDE("/") {
public double apply(double x, double y) { return x / y; }
};
private final String symbol;
BasicOperation(String symbol) {
this.symbol = symbol;
}
@Override public String toString() {
return symbol;
}
}
잘 살펴보면, 각 상수는 apply
메서드를 정의하고있다. 람다를 이용하면 이러한 동작을 파라미터화 해서 보다 간결하게 만들 수 있다.
public enum Operation {
PLUS("+", (x,y) -> x + y),
MINUS("-", (x,y) -> x - y),
TIMES("*", (x,y) -> x*y),
DIVICE("/", (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
로 구현해서 파라미터로 전달한 경우, 추상 메서드를 선언하지 않았다. 하지만 생성자로DoubleBinaryOperator
를 무조건 받아야하기 때문에 다른 Operator가 들어와도 항상 람다를 전달하게 된다.
람다는 함수형 인터페이스에서만 쓰인다. 예를 들어, 추상 클래스의 인스턴스를 만들 때, 람다를 쓸 수 없으니 익명 클래스를 써야한다.
또한, 람다는 자신을 참조할 수 없다. 람다에서의 this
는 바깥 인스턴스를 가리킨다. 반면 익명 클래스에서의 this
는 익명 클래스의 인스턴스 자신을 가리킨다. 따라서 함수 객체가 자신을 참조해야 한다면 반드시 익명 클래스를 써야 한다.
댓글남기기