Skip to content

Latest commit

 

History

History
114 lines (82 loc) · 4.75 KB

42.익명 클래스 보다는 람다를 사용하라.md

File metadata and controls

114 lines (82 loc) · 4.75 KB

예전 함수 객체를 표현하는 방식은 익명클래스로 충분했다.

이번 장에서 익명클래스는 무엇인지, 람다로 대체하면 어떤 이점이 있는지 알아보자

익명클래스

예전에는 자바에서 함수 타입을 표혆라 때, 추상 메서드를 하나만 담은 인터페이스 (드물게는 추상클래스)를 사용했다.

하지만, 익명클래스 방식은 코드가 너무 길기 때문에 함수형 프로그래밍에는 적합하지 않았다.

따라서, 익명클래스를 만들고 싶다면 함수형 인터페이스가 아닌 타입의 인스턴스를 만들때 활용하는 것이 좋다.

public class Anonymous {

    //★★방법 1 : 필드에 익명자식 객체를 생성 
    Backend runa = new Backend() {
        Backend crew = new Backend() {

            String name = "루나";

            @Override
            void mission() {
                System.out.println(name + " 미션을 진행한다.");
            }
        };

        //★★방법2 : 로컬변수의 초기값으로 대입
        void method1() {
            Backend runa = new Backend() {

                String name = "루나";

                @Override
                void mission() {
                    System.out.println(name + " 미션을 진행한다.");
                }
            };

            //로컬변수이기 때문에 메서드에서 바로 사용
            runa.mission();
        }
    };
}

람다식

따라서, 자바 8에 와서는 추상 메서드 하나짜리의 인터페이스는 특별한 의미를 인정받았다.

이러한 인터페이스의 인스턴스를 람다 표현이 가능하게 바꾸게 된 것이다.

public class Lambda {

    public static void main(String[] args) {
        Backend runa = new Backend();
        String name = "루나";
        Backend.mission(runa, (name) -> System.out.println(name + "미션을 진행한다."));
    }
}

위와 같이 표현하면 익명클래스에서 사용했던 자질구레한 코드들이 사라지고 간결하게 표현할 수 있다.

람다식을 작성할 때, 타입을 명시해야 코드가 더 명확할 때만을 제외하고, 람다의 모든 매개변수 타입은 생략하는게 좋다.

아이템 26(제네릭의 로 타입을 쓰지 말라), 아이템 29(제네릭을 써라), 아이템 30(제네릭 메서드를 써라) 의 아이템들은 람다식의 타입 추론을 위해서 더 주의해야되는 내용이다.

Enum 타입에서의 람다

아이템 34에서는 상수별 클래스 몸체를 구현하는 방식보다 열거타입에 인스턴스 변수를 두는 편이 낫다고 했다.

Enum타입에서 람다를 사용하는 것은 그 장점을 극대화해줄 수 있다.

public enum EnumLambda {
    ONE("1", (x) -> x + 1),
    TWO("2", (x) -> x + 2),
    THREE("3", (x) -> x + 3),
    FOUR("4", (x) -> x + 4);

    private final String symbol;
    private final DoubleBinaryOperator op;

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

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

하지만 꼭 상수별 클래스 몸체를 사용할 필요가 없는 것은 아니다.

아래 2가지의 상황에서는 클래스 몸체를 사용하는 것이 좋다.

  1. 람다는 이름이 없다. 고로 문서화하기 어렵다. 코드 자체로 표현이 안될때는 람다를 쓰지 말자.

  2. 열거 타입 생성자에 넘겨지는 인수들의 타입도 컴파일타임에 추론된다. 따라서 열거 타입 생성자 안의 람다는 열거타입의 인스턴스 멤버에 접근할 수 없다.(인스턴스 생성은 런타임에 된다.)

    • 아래의 두번째 이미지에서, 람다 구현은 인스턴스 변수에 접근할 수 없다.

img.png img2.png

람다 사용시 주의점

  • 추상클래스의 인스턴스를 만들때 람다사용은 불가능하다.
  • 추상메서드가 여러개인 인터페이스의 인스턴스도 람다로 표현 불가능하다.
  • 람다의 this는 바깥 인스턴스를 가리킨다. 관련 스택오버플로우 링크
  • 람다를 직렬화하는 것은 삼가야한다. (가상머신별로 다를 수 있기 때문에.) 직렬화 관련 우형 기술블로그 링크

참고 링크

https://javabom.tistory.com/66