본문 바로가기

Java

[Effectiva Java][아이템42] 익명 클래스보다는 람다를 사용하라

[코드 42-1] 익명 클래스의 인스턴스를 함수 객체로 사용한 예시

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

과거 객체 지향 디자인 패턴에서는 익명 클래스면 충분했지만,

코드가 너무 길기 때문에 함수형 인터페이스에는 적절하지 않았다.

 

 

 

자바8에서부터 함수형 인터페이스(추상 메서드 하나를 갖는 인터페이스)를 사용할 수 있게 되었다.

Collections.sort(words, 
	(s1, s2) -> Integer.compare(s1.length(), s2.length())); // 람다

코드가 훨씬 간결해졌다.

매개변수 (s1, s2)의 반환값은 (Comparator<String>), String, int지만 코드에서는 언급이 없다.

컴파일러가 문맥을 살펴서 타입을 추론해주기 때문인데, 추론 규칙은 굉장히 복잡해서 다 이해하는 프로그래머도 거의 없다.

타입을 명시해야 코드가 더 명확할 때(=컴파일러에서 '타입을 알 수 없다'는 오류를 낼 때) 말고는 람다의 모든 매개변수 타입을 생략하면 된다. 

 

 

여기서 코드를 더 줄이면, 자바8에서 추가된 List 인터페이스의 sort 메서드와 비교자 생성 메서드를 사용하면 된다.

Collections.sort(words, comparingInt(String::length));

 

 

아이템34의 Operation 열거타입을 예로 보자.

public enum Operation {
	PLUS("+", (x,y) -> x+y),
    MINUS("-", (x,y) -> x-y),
    TIMES("*", (x,y) -> x*y),
    DIVIDE("/", (x,y) -> x/y);
    ... 생략
}

로 apply 추상메서드 구현부를 람다로 표현할 수 있다.

 

대신 람다는 1-3줄이여야 적당하다. 그 이상으로 길어지면 가독성이 나빠지기 때문에, 반대로 람다를 제거하는 것으로 리팩터링 하는 것이 좋다!

또한 람다의 this는 자기자신이 아닌 바깥 인스턴스를 가리키기 때문에 주의해야 한다.