Notice
Recent Posts
Recent Comments
Link
«   2025/04   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30
Archives
Today
Total
관리 메뉴

전공공부

[아이템 42] 익명 클래스 보다는 람다식을 사용하라 본문

Study/Java

[아이템 42] 익명 클래스 보다는 람다식을 사용하라

monitor 2023. 5. 1. 16:46

 

함수 객체를 표현하는 방식에는 익명 클래스를 이용하여 함수 객체를 표현하여 사용하였다.

 

하지만, 익명 클래스의 인스턴스를 함수 객체로 사용하는 것은 낡은 기법이며 코드를 길어지게 한다.

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

 

기존의 익명 클래스를 활용하여 문자열의 길이를 기준으로 오름차순 정렬을 시도하였다.

 

해당 코드는 자바8에서는 간결히 표현 할 수 있다.

 

추상 메서드 하나짜리 인터페이스는 특별한 의미를 인정 받아서 특별한 대우를 받게 되었다.

 

아래와 같은 람다식으로 말이다.

 

Collection.sort(words, (s1,s2) -> Integer.compare(s1.length(), s2.length()));

 

위와 같이 간결하게 표현이 가능하다. 

 

위 예제는 아이템26의 제네릭은 로 타입의 사용을 자제하라와 아이템 29의 제네릭을 사용하라와 아이템 30의 제네릭 메서드를 사용하라와도 겹치는 예제이다. 로 타입을 사용하게 되면 컴파일러는 제네릭으로 부터 타입 추론을 하는데 이 때, 타입 추론이 불가능하여 타입 에러가 났을 것이고 예제 코드는 제네릭의 메서드를 활용하였기 때문이다.

 

 

제네릭 타입인 T를 가지고 추론을 할 수 있다.


열거 타입 - 람다식의 활용 
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; }
    };
    
    private final String symbol;
    
    Operation(String symbol) {
        this.symbol = symbol;
    }
    
    public abstract double apply(double x, double y);
}

기존의 열거 타입의 활용은 상수별 클래스 몸체를 사용해서 각 상수에서 apply를 구현함

 

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는 내부 인스턴스를 가르킨다.

코드는 해당 블로그를 참조하였다. (https://madplay.github.io/post/prefer-lambdas-to-anonymous-classes)
익명 클래스의 this는 자기 자신 객체를 가르키고, 람다는 바깥의 객체를 가르킨다.

  • 람다도 익명클래스 처럼 직렬화 형태가 달라서 람다를 직렬화하는 일은 극히 삼가야 한다.