java-squid / effective-java

effective java 3e study
105 stars 38 forks source link

[아이템 43] 람다보다는 메서드 참조를 사용하라 #43

Closed wooody92 closed 3 years ago

102092 commented 3 years ago

p260 인스턴스 메서드를 참조하는 두가지 유형.. 한정적, 비한정적

p261 ... 비한정적 참조에서는 함수 객체를 적용하는 시점에 수신 객체를 알려준다. 이를 위해서...

kses1010 commented 3 years ago

@102092

비한정적 메서드 참조

public 또는 protected로 정의한 메서드를 참조할 때 사용하며 static 메서드를 호출하는 것과 유사합니다. 주로 스트림에서 필터와 매핑용도로 많이 사용합니다. 여기서 비한정적이란 작성하는 구문 자체가 특정한 객체를 참조하기 위한 변수를 지정하지 않는다란 의미입니다. 예를 들어 보겠습니다.

String::toUpperCase

String 클래스의 toUpperCase 메서드는 public이나 static이 아니라 반드시 String 클래스가 객체화 되야 호출할 수 있습니다. 그런데 위 코드를 보면 static 메서드를 참조하는 것처럼 정의가 되어있습니다. 이 코드를 람다식으로 바꾸면

(String str) -> str.toUpperCase()

위 코드를 보시면 객체의 생성을 파라미터로 받았습니다. -> 람다 표현식 내부에서 객체 생성이 생겨 객체를 참조할 만한 변수가 외부에 존재하지 않습니다. 그래서 수신객체를 알려주는데 str::toUpperCase 라 표현할 수 없어 String::toUpperCase라 표현하고 String 이라는 수신객체를 알려줍니다.

만약 처리해야할 데이터가 위 사례처럼 하나면 상관없으나, 파라미터가 여러개면 너무 많이 생략하다보니 이 메서드 참조가 어디서 어디까지 한지 알 수가 없습니다. 그래서 주로 스트림에서 많이 사용하는 듯합니다. (매핑, 필터 작업)

한정적 메서드 참조

이미 외부에서 선언된 객체의 메서드를 호출하거나, 객체를 직접 생성해서 메서드를 참조할 때 사용합니다. 여기서 한정적이란 메서드가 특정 객체의 변수로 제한되는걸 말합니다. 예시를 들어보겠습니다.

Calendar.getInstance()::getTime

위 코드 보시면 :: 앞에 객체를 생성하는 코드가 작성 :: 뒤에는 해당 객체에서 호출할 수 있는 getTIme을 지정했습니다. 자바 8이후로 많은 클래스가 생성자를 이용해서 객체 인스턴스하는 것보단 of와 같은 메서들르 이용해서 생성하는 경향이 있습니다. 람다식으로 바꾸면 다음과 같습니다.

Calendar cal = Calendar.getInstance();
() -> cal.getTime()

위 메서드 참조는 큰 단점이 있습니다. 메서드 참조에 의해서 값을 처리할 때마다 Calendar 객체를 생성하여 불필요한 낭비가 발생하게 됩니다. 그래서 한정적 메서드 참조할 때 외부에서 한 번 생성하고 참조하는 형식을 사용합니다.

Calendar cal = Calendar.getInstance(); // 객체 생성
cal::getTime // 메서드 참조. cal 변수를 참조합니다.
kses1010 commented 3 years ago

이펙티브 자바의 글이 너무 어려워서 이 책을 많이 참고했습니다. 좀 더 구체적이고 자세하게 설명되어 있어 큰 도움이 되었어요. http://www.yes24.com/Product/Goods/92529658 image

wooody92 commented 3 years ago

람다 표현식을 메서드 참조 방식으로 변경하면 더욱 간결하고 명확하게 표현할 수 있다. 또한 매개변수 수가 늘어날수록 메서드 참조로 제거할 수 있는 코드량도 늘어난다. 단, 람다가 메서드 참조보다 간결하게 표현되는 경우에는 람다식을 이용하는 편이 좋다.

102092 commented 3 years ago

한정적, 비한정적 한줄로 정리해보기