본문 바로가기

JAVA/Effective Java

item 42) 익명 클래스보다는 람다를 사용하라

728x90
public class LamdaIsBetter {
    public static void main(String[] args) {
        List<String> words = new ArrayList<>();
        Collections.sort(words, new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                return o1.compareTo(o2);
            }
        }); // 익명 클래스

        Collections.sort(words, (s1,s2)-> -s1.compareTo(s2)); //람다 
        
        Collections.sort(words, comparingInt(String::length)); //메소드 참조
        
        words.sort(comparingInt(String::length)); // Java 8 List.sort 메서드 이용

    }
}
  • 익명 클래스 방식은 코드가 너무 길기 때문에 함수형 프로그래밍에 적합하지 않음
  • 익명 클래스는 컴파일 타임에 클래스가 만들어짐(람다는 런타임에 만들어진다.)
  • 대신 람다를 사용하자

 

- 타입을 명시해야 코드가 더 명확할 때를 제외하고는, 람다의 모든 매개변수 타입은 생략하자.(컴파일러의 타입 추론 기능 활용)

- "타입을 알수 없다"는 오류를 낼때만 해당 타입을 명시한다.

- 컴파일러는 타입추론하는데 필요한 타입 정보 대부분을 제네릭에서 얻어온다.(제네릭의 로 타입을 쓰지 말자)

 

 

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; }
    };
    
    private final String symbol;
   
    Operation(String symbol) { this.symbol = symbol; }
    
    @Override public String toString() { return symbol; } 
    public abstract double apply(double x, double y);
}


/*
람다
*/

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);
    }
}

public class Main {
    public static void main(String[] args) {
        // 사용은 아래와 같이
        Operation.PLUS.apply(2, 3);
    }
}

 

 

람다의 단점 , 한계

 

- 람다는 이름이 없고 문서화도 못한다. 코드 자체로 동작이 명확히 설명되지 않거나 코드 줄수가 길어지면 사용 x(코드 길이 : 1~3줄이 적당)

- 열거 타입 생성자 안의 람다는 열거 타입의 인스턴스 멤버에 접근불가 ( 인스턴스는 런타임에 생성, 인수타입은 컴파일 타입에 추론됨)

- 한개의 메소드만 가질 수 잇음

- this

 

람다의 this는 람다를 둘러싸고 있는 클래스를 가르키고,

익명 클래스의 this 는 익명 클래스의 인스턴스를 가르킨다.

함수 객체가 자기 자신을 참조한다면, 반드시 익명 클래스를 사용해야한다.

 Collections.sort(words, new Comparator<String>() {
            String a="boo";
            @Override
            public int compare(String o1, String o2) {
                System.out.println(this.getClass() + " "  + this.a);
                return o1.compareTo(o2);
            }
        }); // 익명 클래스

        Collections.sort(words, (s1,s2)->{
            System.out.println(this.getClass());
            return -s1.compareTo(s2);
        } ); //람다
        
        
        
  /*
  	class Probe$1 boo
	class Probe
  */