티스토리 뷰
반응형
예전 자바에서는 함수 객체를 만드는 주요 수단은 익명 클래스였다.
함수 객체 : 추상 메서드를 하나만 담은 인터페이스의 인스턴스
//익명 클래스의 인스턴스를 함수 객체로 사용 - 낡은 기법
Collections.sort(words, new Comparator<String>() {
@Override
public int compare(String s1, String s2) {
return Integer.compare(s1.length(), s2.length());
}
});
람다식
자바8부터 추상 메서드 하나만 담은 함수형 인터페이스의 인스턴스를 람다식을 이용해 만들 수 있게 되었다.
람다는 함수나 익명 클래스와 개념은 비슷 but 코드는 더 간결하고 명확함
//람다식을 함수 객체로 사용 - 익명 클래스 대체
Collections.sort(words,(s1,s2)->Integer.compare(s1.length(),s2.length()));
매개변수(s1,s2)와 반환값의 타입이 코드에 나타나있지 않다.
컴파일러가 대신 타입을 추론해준다.
상황에 따라 컴파일러가 타입을 결정하지 못할때만 명시해주면 된다.
컴파일러가 타입 추론시에 타입 정보를 제네릭에서 얻어온다. → 로 타입이 아닌 매개변수화 타입 사용하자.
열거 타입에서 람다식 사용하기
상수마다 메서드 동작을 다르게 해야하는 경우에 상수별 메서드 구현을 했었다. [아이템34]
public enum 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; }};
public abstract double apply(double x, double y);
private final String symbol;
Operation(String symbol) { this.symbol = symbol; }
@Override public String toString() { return symbol; }
}
위 코드에서 상수별 클래스 몸체를 구현하는 방식보다 열거 타입에 인스턴스 필드를 두는 편이 낫다.
람다를 이용하여 인스턴스 필드로 상수별로 다르게 동작하게 할 수 있다.
//람다를 인스턴스 필드에 저장해 상수별 동작을 구현한 열거 타입 - 간결하고 깔끔
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);
}
}
람다와 익명 클래스
- 람다는 이름이 없고 문서화도 못하므로 코드 자체로 동작이 명확히 설명되지 않거나 코드 줄 수가 많아지면 람다를 쓰지 말아야 한다.
- 람다는 한줄에서 세줄안에 끝내는게 좋다.
- 함수형 인터페이스(추상 메서드가 하나인)에서만 쓰임 (추상 클래스의 인스턴스를 만들때는 익명 클래스 써야함)
- 추상 메서드가 여러개인 인터페이스의 인스턴스를 만들때도 익명 클래스를 쓸 수 있음
- 람다는 자신을 참조할 수 없음 (람다에서의 this 는 바깥 인스턴스를 가리킴) → 자신을 참조해야한다면 무조건 익명 클래스 사용하라.
- 람다와 익명 클래스 모두 직렬화가 구현별로 다를 수 있으므로 직렬화를 삼가고 private 정적 중첩 클래스의 인스턴스[아이템24]를 사용하라.
결론
익명 클래스는 함수형 인터페이스가 아닌 타입의 인스턴스를 만들때만 사용하고 그 외에는 람다를 사용하라.
람다는 간결하고 쉽게 표현할 수 있어 자바의 함수형 프로그래밍의 지평을 열었다.
반응형
'Java > Effective Java' 카테고리의 다른 글
[Effective Java] 44.표준 함수형 인터페이스를 사용하라 (0) | 2022.04.01 |
---|---|
[Effective Java] 43.람다보다는 메서드 참조를 사용하라 (0) | 2022.04.01 |
[Effective Java] 41.정의하려는 것이 타입이라면 마커 인터페이스를 사용하라 (0) | 2022.03.31 |
[Effective Java] 40.@Override 애너테이션을 일관되게 사용하라 (0) | 2022.03.31 |
[Effective Java] 39.명명 패턴보다 애너테이션을 사용하라 (0) | 2022.03.28 |
댓글