카샤의 만개시기

익명클래스 vs 람다 본문

Java/POJO

익명클래스 vs 람다

SKaSha 2019. 6. 30. 23:57

인터페이스는 직접 객체화할 수 없기 때문에 구현 클래스를 이용하는데 일회성으로 사용하는 구현 클래스를 계속 선언하는 것은 비효율적이기 때문에 익명 클래스람다를 이용하여 구현 클래스를 선언합니다.

익명 클래스

익명 클래스는 코드가 너무 길어 함수형 프로그래밍 방식에 적합하지 않습니다.
익명 클래스에 대해 알고 싶다면 다음 글을 참조해주세요.
중첩클래스 (내부클래스, 정적 중첩클래스, 지역클래스, 익명클래스)

함수 객체 (Function Object)

특정 동작을 목적으로 추상 메서드를 하나만 담은 인터페이스나 추상 클래스를 함수 객체라합니다.

람다

JDK 1.8 이후로는 함수 객체의 인스턴스를 람다식으로 만들어 사용할수 있습니다.

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

람다를 이용하여 다음과 같이 줄여 쓸 수 있습니다.
Collections.sort(list, (s1, s2) -> Integer.compare(s1.length(), s2.length()));

Collections.sort(list, Comparator.comparingInt(String::length));

공통점

익명클래스나 람다가 선언되어 있는 바깥 클래스의 멤버 변수나 메서드에 접근할수 있습니다.
하지만 멤버 변수나 메서드의 매개변수에 접근하기 위해서는 해당 변수들이 final의 특성을 가지고 있어야 합니다.
이 말은 final로 선언하지 않았더라도 변수를 변경하지 않으면 실질적으로 final과 같기때문에 final 선언을 생략할수 있음을 말합니다.

차이점

  1. 익명클래스와 람다에서의 this의 의미는 다르다!
    익명클래스의 this는 익명클래스 자신을 가리키지만 람다에서의 this는 선언된 클래스를 가리킵니다.
  2. 람다는 은닉 변수(Shadow Variable)을 허용하지 않는다!
    익명 클래스는 변수를 선언하여 사용할 수 있지만 람다는 이를 허용하지 않습니다.
  3. 람다는 인터페이스에 반드시 하나의 메서드만 가지고 있어야 한다!
    인터페이스에 @FunctionalInterface 어노테이션을 붙이면 두개 이상의 추상 메서드가 선언되었을 경우 컴파일 에러를 발생시킨다.
  4. 람다는 하기와 같이, 같은 시그니처를 가지는 인터페이스에 대하여 의미가 모호해 집니다!
interface Hello {
    void print();
}

interface World {  
    void print();  
}

public static void action(Hello hello) {  
    hello.print();  
}

public static void action(World world) {  
    world.print();  
}

public void foo() {  
    // 익명클래스는 다음과 같이 타입이 지정되어 의미가 분명함  
    action(new Hello() {  
        public void print() {  
            System.out.println("Hello");  
        }  
    });

    // 람다는 Hello 객체인지 World 객체인지 불분명함
    action(()-> System.out.println("Hello"));
     // 다음과 같이 타입을 지정해 주어야 함
    action((Hello) () -> System.out.println("Hello"));
}
Comments