IntelliJ에서 자주 보이는 메세지...?
Lambda can be replaced with method reference
Anonymous new Consumer() can be replaced with lambda
Anonymous new Consumer() can be replaced with method reference
IntelliJ를 이용해서 개발하다보면 위와같은 메세지와 함께 여러 Refacotring 들이 생깁니다.
그리고 어떤 옵션을 선택하는 순간 마법처럼 IntelliJ가 코드를 간결하게 만들어줍니다.
IntelliJ의 유혹(?)
이런 IntelliJ의 유혹(?)에 견디지 못해 막 실행하다보면 왜 이렇게 코드가 변했는지 알지 못하고 해당 로직에서 문제가 발생했을 때 트러블 슈팅에서 애를 먹게 되는 경우도 있습니다.
IntelliJ가 지원하는 익명 클래스 → Labmda 의 변환
기본적으로 위 메세지는 익명 클래스와 Lambda 에 대한 메세지입니다.
익명 클래스 → Labmda 의 과정을 이해한다면 트러블 슈팅과정에서도 훨씬 수월해질것이라 생각합니다.
익명 클래스에서의 시작
Java 7에서는 Collection.sort()
, List.forEach()
를 아래와 같이 익명클래스를(혹은 따로 Comparator
, Consumer
를 구현한 클래스를)
만들어서 사용해야 했습니다.
List<Integer> testList = new ArrayList<>();
//sort를 사용하기 위해 익명 클래스를 생성해야 한다.
Collections.sort(testList, new Comparator<Integer>(){
@Override
public int compare(Integer prev, Integer next) {
return prev.compareTo(next);
}
});
//forEach를 사용하기 위해 익명 클래스를 생성해야 한다.
testList.forEach(new Consumer<Integer>() {
@Override
public void accept(Integer integer) {
System.out.println(integer);
}
});
그런데 생각해보면 Compartor
를 구현할 메소드는 int compare(T o1, T o2)
하나이고
이는 타입추론이 어느정도 가능하다는 뜻이 됩니다.
(Consumer
도 동일합니다.)
익명 클래스 줄여보기 1
타입 추론이 가능하다는 것은 코드의 라인수를 줄일 수 있다는 뜻이 되기도 합니다.
그래서 java8 에서는 타입 추론을 이용해 아래와 같이 코드를 줄일 수 있게되었습니다.
List<Integer> testList = new ArrayList<>();
// Comparator의 어떤 함수를 구현할 것인지 추론이 가능하기 때문에 아래와 같이 코드를 줄일 수 있게됨
Collections.sort(testList, (Integer prev, Integer next) -> {
return prev.compareTo(next);
});
// Consumer의 어떤 함수를 구현할 것인지 추론이 가능하기 때문에 아래와 같이 코드를 줄일 수 있게됨
testList.forEach((Integer integer) -> {
System.out.println(integer);
});
익명 클래스 줄여보기 2
생각해보면 이미 testList
라는 컬렉션은 제네릭을 통해 이미 타입이 정해져 있습니다.
그렇다면 Comparator
의 매개변수인 (Integer prev, Integer next)
의 타입도 추론하여 생략할 수 있게 됩니다.
List<Integer> testList = new ArrayList<>();
// testList에서 이미 제네릭으로 타입이 정해져있으므로 타입 생략 가능
Collections.sort(testList, (prev,next) -> {
return prev.compareTo(next);
});
// testList에서 이미 제네릭으로 타입이 정해져있으므로 타입 생략 가능
testList.forEach((integer) -> {
System.out.println(integer);
});
익명 클래스 줄여보기 3
그리고 로직이 1 Line인 메소드는 굳이 Brace(괄호)가 필요없어지게 됩니다.
Brace가 필요없어지게 된 메소드는 retudrn
도 줄일 수 있게됩니다.
→ return
값이 필요한 메소드에는 자동으로 return
이 붙은 형태로 동작하게 됨
List<Integer> testList = new ArrayList<>();
// brace가 생략된 형태로, 구현한 메소드가 return값이 필요한 메소드이므로
// return이 붙은 형태로 동작
Collections.sort(testList, (prev, next) -> prev.compareTo(next));
// brace가 생략된 형태로, 구현한 메소드가 void이므로
// return 없이 동작
testList.forEach((integer) -> System.out.println(integer));
익명 클래스 줄여보기 4
{코드라인 1 Line} && {사용하는 메소드의 파라미터가 1개}
위 조건을 만족한다면 메서드 참조를 통해 간략히 할 수 있게 됩니다.
List<Integer> testList = new ArrayList<>();
Collections.sort(testList, (prev, next) -> prev.compareTo(next));
// 코드라인이 1 Line이고 사용하는 메소드의 파라미터가 1개일 경우
// 메서드 참조를 통해 간략히 할 수 있게 됩니다.
testList.forEach(System.out::println);
'Java' 카테고리의 다른 글
외부 API 연동 테스트 코드 @RestClientTest (2) | 2021.10.17 |
---|---|
@SpringBootTest / @DataJpaTest 차이점 과 JPA 영속성 컨텍스트 (5) | 2021.09.12 |
람다 캡처링 :: Variable used in lambda expression should be final or effectively final의 이유 (7) | 2021.07.14 |
Mockito @Mock @MockBean @Spy @SpyBean 차이점 (27) | 2020.09.13 |
@NoargsConstructor(AccessLevel.PROTECTED) 와 @Builder (5) | 2020.07.31 |