9장 리펙터링, 테스팅, 디버깅

su dong·2023년 9월 21일
0

핵심 내용

  • 람다 표현식으로 코드 리팩터링하기
  • 람다 표현식이 객체지향 설계 패턴에 미치는 영향
  • 람다 표현식 테스팅
  • 람다 표현식과 스트림 API 사용 코드 디버깅

9.1 가독성과 유연성을 개선하는 리팩토링

람다표현식을 활용하면 동작을 파라미터화 할 수 있음.

9.1.1 코드 가독성 개선

코드 가독성 개선이란 '어떤 코드를 다른 사람도 쉽게 이해할 수 있음'을 의미한다. 유지보수성 up!
3가지 예제를 다뤄볼 것이다.

  • 익명 클래스 -> 람다표현식
  • 람다 표현식 -> 메서드 참조
  • 명령형 데이터 처리 -> 스트림

9.1.2 익명 클래스-> 람다 표현식

Runnable r1 = new Runnable(){
	public void run(){
    	System.out.println("Hello");
    }
}

Runnable r2 = () -> System.out.println("Hello");

하지만 모든 익명 클래스를 람다 표현식으로 변환할 수 있는 것은 아니다.
첫째, 익명 클래스에서 사용한 this 와 super는 람다표현식에서 다른 의미를 가진다. 익명 클래스에서 this는 자기 자신을 가르키지만, 람다에서 this는 람다를 감싸는 클래스를 가리킨다.
둘째, 익명 클래스는 감싸고 있는 클래스의 변수를 가릴 수 있다.(섀도 변수) 하지만 다음 코드에서 보여주는 것처럼 람다 표현식으로는 변수를 가릴 수 없다.

int a = 10;
Runnable r1 = () ->{
	int a =2; // 컴파일 에러
    System.out.println(a);
}

Runnable r2 = new Runnable(){
	public void run(){
    	int a = 2; // 잘 작동한다.
        System.out.println(a);
    }
};

마지막으로 익명 클래스를 람다 표현식으로 바꾸면 콘텍스트 오버로딩에 따른 모호함이 초래될 수 있다. 익명 클래스는 인스턴스화할 때 명시적으로 형식이 정해지는 반면 람다의 형식은 콘텍스트에 따라 달라지기 때문이다.
아래 코드에서는 Task라는 Runnable과 같은 시그니처를 갖는 함수형 인터페이스를 선언한다.

interface Task{
	public void execute();
}
public stativ void doSomething(Runnable r){r.run();}
public stativ void doSomething(Task a){r.execute();}

Task를 구현하는 익명 클래스를 전달할 수 있다

doSomething(new Task(){
	public void execute(){
    	System.out.println("Danger danger!!");
    }
}

하지만 익명 클래스를 람다 표현식으로 바꾸면 메서드를 호출할 때 Runnable과 Task 모두 대상 형식이 될 수 있으므로 문제가 생긴다.

doSomething(()-> System.out.println("Danger danger!!"));

즉 doSomething(Runnable)과 doSomething(Task)중 어떤 것을 가르키는지 알지 못하는 모호함이 생긴다.
명시적 형변환 (Task)를 통해서 모호함을 제거할 수 있다.

doSomething((Task)()-> System.out.println("Danger danger!!"));

다행인 것은, IDE에서 이런 오류를 잡아준다!


9.1.3 람다 표현식 -> 메서드 참조

profile
사람들을 돕는 문제 해결사, 개발자 sudong입니다. 반갑습니다. tkddlsqkr21@gmail.com

0개의 댓글