Java

자바 익명클래스와 자바 람다 (Java Anonymous class, Java Lambda) 1편

Declan Andrew 2019. 8. 18. 23:53
반응형

자바의 람다는 익명클래스와 매우 비슷한 모습을 하고있다.

그러나 둘은 아주 다르다.

 

 

익명클래스

 

 

일단 익명클래스는 어쨌거나 사용할 때 보통 객체와 동일하게 힙에 할당이 된다.

메인메소드 내에서 익명클래스를 사용하면 컴파일 시에 $1, $2 등과 같은 순서대로

클래스파일이 생성이 된다.

 

예시로, 평범한 인터페이스를 하나 선언한다.

추상클래스나 일반 클래스도 상관없다.

interface Test{
	
	public int getNum();
	
}

 

그 후, 메인에서 바로 사용하기 위해 재정의를 해준다.

public class LambdaTest {
	public static void main(String[] args) {
		Test t1 = new Test(){ 
				public int num = 10; 
				 
				public int getNum(){ return this.num; } 
			}; 
		
		System.out.println(t1.getNum());
	}
}

 

이렇게 하면 메인함수에서 바로 구현체를 만들어 사용할 수 있다는 특징이 있다.

이것이 익명 클래스의 기본이다.

 

익명 클래스 생성 시 추가되는 파일 

또한 익명클래스 사용 시 위 사진처럼 $1 클래스 파일만들어진다.

그리고 클래스이므로 객체를 계속 생성하여 사용하여야한다. ( 메모리에 계속 증가 )

 

 

람다는 그러면 무슨 차이점이 있는가?

 

일단, 자바 객체 생성 후 메소드를 찍어보면 클래스명.메소드() 호출 하는것을 볼 수 있을것이다.

객체명.메소드()가 아니라 클래스명.메소드().. 이것은 어떻게 된 일이냐면

자바 Permanent 영역에 메소드를 저장해놓는데,

이 메소드는 한번 저장해놓고 객체들이 이 주소지로 넘어오는 것이다.

한번 만들어놓고 계속 참조하는것이다.

 

그러면 이게 람다와 무슨 상관이 있는가?

 

람다는 식 그 자체이다.

익명클래스처럼 구현을 하는 것 같아도 위에 말한 메소드처럼 굴러간다는 것이다.

즉, 이 주소로 바로 Branch하게 된다는 것이다.

익명클래스처럼 객체를 생성하지않고 바로 메소드의 주소로 이동한다고 보면 된다.

 

무엇보다 코드의 길이를 확 줄일수 있다는 장점도 있고, 가독성이 떨어진다는 단점도 가지고 있지만

여러모로 유용하다는 장점이 있다.

최근 트렌드는 함수형 프로그래밍이므로 잘 알아두는 것이 좋다.

 

람다에 대한 예시를 들자면

Comparator<Point> comparator = (Point p1, Point p2) -> {
            if (p1.x > p2.x) {
                return 1; 
            }else if(p1.x < p2.x){
                return -1;
            }else{
                return 0;
            }
        };
        Collections.sort(pointList, comparator);

첫번째 방법으로는 사용 전에 미리 식을 정의 해두는 것이 있고.

 

Collections.sort(pointList, (Point p1, Point p2) -> {
            if (p1.x > p2.x) {
                return 1; // x에 대해서는 오름차순
            }else if(p1.x < p2.x){
                return -1;
            }
            return 0;
        })

두번째 방법으로는 사용 할 때 매개변수를 재정의해버리는 것이 있다.

 

사용방법은 예시는 위와 같고, 사용법은 아래와 같다.

인터페이스 인터페이스 명 = (매개변수 자료형 매개변수이름) -> { 메소드 본체 }

 

사용 시 참고 사항

1. 인터페이스 내의 메소드가 하나만 존재하여야한다. (default와 static메소드는 상관이 없다.)

2. 여러개를 생략할 수 있다, 매개변수의 괄호 그리고 자료형, 메소드의 몸체가 되는 부분의 괄호

3. return 생략시 ;(semi colon)도 생략하여야한다.

4. new가 애초에 생략되어 있을 뿐이다. 기본 골자는 익명클래스와 비슷하긴 하다.

 

API 문서에서 @FunctionalInterface 라고 표시 해놓은것에선 무조건 된다.

물론 우리도 사용하기 위해선 인터페이스에 어노테이션으로 적어두어야한다.

 

나머지는 다음 글에서 자세히 설명하도록 하겠다.

반응형