본문 바로가기

JAVA

Java 익명 클래스와 람다 표현식의 다른 점

모든 익명클래스를 람다 표현식으로 바꾸는 것이 가능할까? 모든 익명클래스를 람다표현식으로 리팩토링하고 싶지만, 그것은 불가능하다.

익명 클래스와 람다 표현식의 다른점을 살펴보고 어떤 점이 문제가 되는지 알아보자.

1. this 가 가리키고 있는 것

익명 클래스에서의 this는 자기 자신을 가리키지만, 람다 표현식에서는 람다를 감싸는 클래스를 가리킨다.

실험을 위해 간단한 테스트 코드를 준비했다. T1클래스에 testLambda와 testAnonymous라는 메소드를 만들었다. testLambda의 경우 람다식을 이용해서 this를 출력하고, testAnonymous는 익명클래스를 이용해서 this를 출력한다.

Main class에서는 T1 클래스로 인스턴스를 생성하여 testLambda와 testAnonymous를 실행시킨다.

class T1 {
	void testLambda() {
		Runnable r = () -> {
			System.out.println("lambda : " + this);
		};
		r.run();
	}

	void testAnonymous() {
		Runnable r = new Runnable() {
			public void run() {
				System.out.println("anonymous : " + this);
			}
		};
		r.run();
	}
}

public class Main {
	public static void main(String[] args) {
		T1 t = new T1();
		t.testLambda();
		t.testAnonymous();
    }
}

아래는 테스트 결과이다.

lambda : T1@e6ea0c6
anonymous : T1$1@39ed3c8d

람다의 경우 T1이라는 클래스가 this인 반면에, 익명 클래스의 경우 T1$1 로 1이라는 내부클래스가 this 인것을 확인할 수 있다.

2. 지역변수의 재선언 가능 여부

a라는 변수를 미리 선언하여 10이라는 값을 할당해 놓았다. 람다식에서 이 a를 다시 선언해서 사용하는 것이 가능할까? 

람다 표현식에서는 지역변수를 재선언 할 수 없음

불가능하다. IDE에서 친절하게도 람다표현식에서는 지역변수를 재선언할 수 없다고 알려주고 있다. 반면 익명클래스에서는 a라는 변수를 선언하여 사용하는 것이 가능하다.

3. 람다표현식의 모호함

WorkA와 WorkB라는 interface에 둘 다 execute라는 메소드가 선언되어 있다. parameter로는 아무것도 받지 않고 return도 하지 않는다. Main클래스에서 각각 WorkA와 WorkB를 받는 doSomething이라는 static method를 정의한다. main method에서 doSomething의 parameter를 각각 익명클래스와 람다식으로 넘겨줘봤다.

interface WorkA {
	public void execute();
}

interface WorkB {
	public void execute();
}

public class Main {
	public static void doSomething(WorkA workA) {
		workA.execute();
	}

	public static void doSomething(WorkB workB) {
		workB.execute();
	}

	public static void main(String[] args) {
		//익명 클래스는 모호성이 없다.  
		doSomething(new WorkA() {
			public void execute() {
				System.out.println("workA");
			}
		});
		//람다 표현식은 모호함이 생긴다. WorkA인지 WorkB인지 특정할 수 없다.
		doSomething(() -> {
			System.out.println("what is my work?");
		});
    }
}

람다식의 경우 어떤 인터페이스를 구현한 것인지 특정할 수 없기 때문에 컴파일 오류가 발생하게 된다.

Eclipse가 doSomething이 모호하다고 알려준다.

IDE에서도 빨간 밑줄이 그어지며 모호하다고 알려주고 있다. 모호함을 제거하기 위해서는 명시적 형변환 (WorkA )을 사용해야 한다.

doSomething((WorkA) () -> {
	System.out.println("what is my work?");
});
반응형

'JAVA' 카테고리의 다른 글

Adapter Pattern 과 SLF4J  (0) 2021.08.27
Log4j 알아보기  (0) 2021.08.16
Volatile Java  (0) 2021.08.16
LinkedHashMap 알아보기  (0) 2020.12.11
Java String + 연산에 대한 이해  (0) 2020.11.21